diff options
Diffstat (limited to 'spec/frontend')
-rw-r--r-- | spec/frontend/helpers/url_util_helper.js | 7 | ||||
-rw-r--r-- | spec/frontend/issues/components/issue_spec.js | 222 | ||||
-rw-r--r-- | spec/frontend/issues/components/issues_app_spec.js | 234 | ||||
-rw-r--r-- | spec/frontend/issues/mock_data.js | 1491 | ||||
-rw-r--r-- | spec/frontend/issues/stores/modules/issues_list/actions_spec.js | 111 | ||||
-rw-r--r-- | spec/frontend/issues/stores/modules/issues_list/getters_spec.js | 27 | ||||
-rw-r--r-- | spec/frontend/issues/stores/modules/issues_list/mutations_spec.js | 66 | ||||
-rw-r--r-- | spec/frontend/lib/utils/url_utility_spec.js | 8 |
8 files changed, 2159 insertions, 7 deletions
diff --git a/spec/frontend/helpers/url_util_helper.js b/spec/frontend/helpers/url_util_helper.js new file mode 100644 index 00000000000..d28e9aa7bf9 --- /dev/null +++ b/spec/frontend/helpers/url_util_helper.js @@ -0,0 +1,7 @@ +// eslint-disable-next-line import/prefer-default-export +export const setWindowLocation = value => { + Object.defineProperty(window, 'location', { + writable: true, + value, + }); +}; diff --git a/spec/frontend/issues/components/issue_spec.js b/spec/frontend/issues/components/issue_spec.js new file mode 100644 index 00000000000..66252ad4d97 --- /dev/null +++ b/spec/frontend/issues/components/issue_spec.js @@ -0,0 +1,222 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import IssueComponent from '~/issues/components/issue.vue'; +import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import { singleIssueData } from '../mock_data'; + +const localVue = createLocalVue(); + +describe('Issue component', () => { + let wrapper; + + const factory = (props = {}, options = {}) => { + const propsData = { + issue: singleIssueData, + isBulkUpdating: false, + canBulkUpdate: true, + ...props, + }; + + wrapper = shallowMount(localVue.extend(IssueComponent), { + localVue, + propsData, + ...options, + }); + }; + + it('renders the issue title', () => { + factory(); + + const issueTitle = wrapper.find('.issue-title-text > a'); + + expect(issueTitle.exists()).toBe(true); + expect(issueTitle.text()).toBe(singleIssueData.title); + }); + + it('links to the issue details page', () => { + factory(); + + const issueTitle = wrapper.find('.issue-title-text > a'); + + expect(issueTitle.attributes('href')).toBe(singleIssueData.web_url); + }); + + it('renders issue confidential icon', () => { + factory(); + + const confidentialIcon = wrapper.find('.js-issue-confidential-icon'); + + expect(confidentialIcon.exists()).toBe(true); + }); + + it('renders issue tasks', () => { + const issue = { ...singleIssueData }; + issue.has_tasks = true; + issue.task_status = '0 or 2 completed'; + + factory({ issue }); + + const issueTasksWrapper = wrapper.find('.task-status'); + + expect(issueTasksWrapper.exists()).toBe(true); + expect(issueTasksWrapper.text()).toBe(issue.task_status); + }); + + it('renders issue reference path', () => { + factory(); + + const referencePath = wrapper.find('.issuable-reference'); + + expect(referencePath.exists()).toBe(true); + expect(referencePath.text()).toBe(singleIssueData.reference_path); + }); + + it('renders issue created date', () => { + factory(); + + const issueCreatedDate = wrapper.find('.issuable-authored').find(TimeAgoTooltip); + + expect(issueCreatedDate.exists()).toBe(true); + expect(issueCreatedDate.props('time')).toBe(singleIssueData.created_at); + }); + + it('renders issue author', () => { + factory(); + + const issueAuthor = wrapper.find('.issuable-authored .author-link'); + + expect(issueAuthor.exists()).toBe(true); + expect(issueAuthor.text()).toBe(singleIssueData.author.name); + expect(issueAuthor.attributes('href')).toBe(singleIssueData.author.web_url); + }); + + it('renders issue milestone', () => { + const issue = { ...singleIssueData }; + issue.milestone = { + web_url: 'http://hello.world', + title: 'Hello milestone', + }; + + factory({ issue }); + + const issueMilestone = wrapper.find('.issuable-milestone'); + + expect(issueMilestone.exists()).toBe(true); + expect(issueMilestone.text()).toBe(issue.milestone.title); + expect(issueMilestone.find('a').attributes('href')).toBe(issue.milestone.web_url); + }); + + it('renders issue weight', () => { + factory(); + + const issueWeight = wrapper.find('.issuable-weight'); + + expect(issueWeight.exists()).toBe(true); + expect(issueWeight.text()).toBe(`${singleIssueData.weight}`); + }); + + it('renders issue "CLOSED" if issue is closed', () => { + const issue = { ...singleIssueData }; + issue.state = 'closed'; + + factory({ issue }); + + const issueStateWrapper = wrapper.find('.issuable-status'); + + expect(issueStateWrapper.exists()).toBe(true); + expect(issueStateWrapper.text()).toBe('CLOSED'); + }); + + it('renders issue merge request count', () => { + const issue = { ...singleIssueData }; + issue.merge_requests_count = '20'; + + factory({ issue }); + + const issueMRCount = wrapper.find('.issuable-mr'); + + expect(issueMRCount.exists()).toBe(true); + expect(issueMRCount.text()).toBe(issue.merge_requests_count); + }); + + describe('Issue upvotes', () => { + let issue; + + beforeEach(() => { + issue = { ...singleIssueData }; + issue.upvotes = '5'; + }); + + it('does not render if upvotes is 0', () => { + issue.upvotes = 0; + + factory({ issue }); + + const issueUpvotes = wrapper.find('.issuable-upvotes'); + + expect(issueUpvotes.exists()).toBe(false); + }); + + it('renders upvotes count', () => { + factory({ issue }); + + const issueUpvotes = wrapper.find('.issuable-upvotes'); + + expect(issueUpvotes.exists()).toBe(true); + expect(issueUpvotes.text()).toBe(issue.upvotes); + }); + }); + + describe('Issue downvotes', () => { + let issue; + + beforeEach(() => { + issue = { ...singleIssueData }; + issue.downvotes = '5'; + }); + + it('does not render if downvotes is 0', () => { + issue.downvotes = 0; + + factory({ issue }); + + const issueDownvotes = wrapper.find('.issuable-downvotes'); + + expect(issueDownvotes.exists()).toBe(false); + }); + + it('renders downvotes count', () => { + factory({ issue }); + + const issueDownvotes = wrapper.find('.issuable-downvotes'); + + expect(issueDownvotes.exists()).toBe(true); + expect(issueDownvotes.text()).toBe(issue.downvotes); + }); + }); + + describe('Issue comments', () => { + let issue; + + beforeEach(() => { + issue = { ...singleIssueData }; + issue.note_count = '5'; + }); + + it('renders 0 if the issue has no comments', () => { + issue.note_count = null; + + factory({ issue }); + + const issueComments = wrapper.find('.issuable-comments'); + + expect(issueComments.text()).toBe('0'); + }); + + it('renders issue comments count', () => { + factory({ issue }); + + const issueComments = wrapper.find('.issuable-comments'); + expect(issueComments.text()).toBe(issue.note_count); + }); + }); +}); diff --git a/spec/frontend/issues/components/issues_app_spec.js b/spec/frontend/issues/components/issues_app_spec.js new file mode 100644 index 00000000000..b8dcf72fa43 --- /dev/null +++ b/spec/frontend/issues/components/issues_app_spec.js @@ -0,0 +1,234 @@ +import Vuex from 'vuex'; +import { mount, createLocalVue } from '@vue/test-utils'; +import { TEST_HOST } from 'helpers/test_constants'; +import { GlPagination } from '@gitlab/ui'; +import IssuesApp from '~/issues/components/issues_app.vue'; +import IssueComponent from '~/issues/components/issue.vue'; +import IssuesEmptyState from '~/issues/components/empty_state.vue'; +import IssuesLoadingState from '~/issues/components/loading_state.vue'; +import * as getters from '~/issues/stores/modules/issues_list/getters'; +import { issuesResponseData } from '../mock_data'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('Issues app', () => { + let store; + let state; + let actions; + let wrapper; + let mockedProjectSelect; + let mockedIssuableIndex; + let mockedFilteredSearch; + + const factory = (props = {}, options = {}) => { + const propsData = { + endpoint: TEST_HOST, + createPath: '/', + projectSelect: mockedProjectSelect, + canBulkUpdate: true, + issuableIndex: mockedIssuableIndex, + filteredSearch: mockedFilteredSearch, + emptyStateSvgPath: '/', + emptyStateLoadingDisabledSvgPath: '/', + ...props, + }; + + store = new Vuex.Store({ + modules: { + issuesList: { + namespaced: true, + state, + actions, + getters, + }, + }, + }); + + wrapper = mount(localVue.extend(IssuesApp), { + localVue, + store, + sync: false, + propsData, + ...options, + }); + }; + + beforeEach(() => { + state = { + loading: false, + filters: '', + issues: null, + isBulkUpdating: false, + currentPage: 1, + totalItems: 1, + }; + + actions = { + fetchIssues: jest.fn(), + setCurrentPage: jest.fn(), + }; + + mockedFilteredSearch = { + updateObject: jest.fn(), + clearSearch: jest.fn(), + loadSearchParamsFromURL: jest.fn(), + }; + + mockedIssuableIndex = { + bulkUpdateSidebar: { + bindEvents: jest.fn(), + initDomElements: jest.fn(), + }, + }; + + mockedProjectSelect = jest.fn(); + + document.body.innerHTML = ''; + window.gon = {}; + }); + + it('fetches issues when mounted', () => { + factory(); + expect(actions.fetchIssues).toHaveBeenCalled(); + expect(actions.fetchIssues.mock.calls[0]).toContain(TEST_HOST); + }); + + it('renders loading state when fetching issues', () => { + state.loading = true; + factory(); + + const loadingState = wrapper.find(IssuesLoadingState); + + expect(loadingState.exists()).toBe(true); + expect(loadingState.classes()).toContain('js-issues-loading'); + }); + + it('renders empty state if no issues', () => { + state.issues = []; + factory(); + + const emptyState = wrapper.find(IssuesEmptyState); + + expect(emptyState.exists()).toBe(true); + }); + + it('renders issues list when issues are present', () => { + state.issues = issuesResponseData.slice(0, 10); + factory(); + + const issueComponent = wrapper.find(IssueComponent); + + expect(issueComponent.exists()).toBe(true); + expect(wrapper.findAll(IssueComponent).length).toEqual(10); + }); + + it('renders issues list pagination', () => { + state.issues = issuesResponseData; + factory(); + expect(wrapper.find(GlPagination).exists()).toBe(true); + }); + + it('initializes issues page events', () => { + state.issues = issuesResponseData; + factory(); + + wrapper.setData({ isInProjectPage: true }); + wrapper.vm.setupExternalEvents(); + + expect(mockedIssuableIndex.bulkUpdateSidebar.bindEvents).toHaveBeenCalled(); + expect(mockedIssuableIndex.bulkUpdateSidebar.initDomElements).toHaveBeenCalled(); + }); + + it('initializes project selector in issues dashboard page', () => { + state.issues = issuesResponseData; + factory( + {}, + { + data() { + return { + ISSUES_PER_PAGE: 20, + isInGroupsPage: false, + isInProjectPage: false, + isInDashboardPage: true, + isLoadingDisabled: false, + }; + }, + }, + ); + + expect(mockedProjectSelect).toHaveBeenCalled(); + }); + + it('initializes project selector in groups issues page', () => { + state.issues = issuesResponseData; + factory( + {}, + { + data() { + return { + ISSUES_PER_PAGE: 20, + isInGroupsPage: true, + isInProjectPage: false, + isInDashboardPage: false, + isLoadingDisabled: false, + }; + }, + }, + ); + + expect(mockedProjectSelect).toHaveBeenCalled(); + }); + + describe('Issues filters', () => { + it('updates filters when the current page changes', () => { + const page = 2; + + document.body.innerHTML = '<div id="content-body"></div>'; + state.issues = issuesResponseData; + factory(); + + wrapper.vm.updatePage(page); + + expect(mockedFilteredSearch.updateObject).toHaveBeenCalled(); + expect(actions.setCurrentPage.mock.calls[0]).toContain(page); + }); + + it('update filters when a label is clicked', () => { + const label = 'Hello'; + state.issues = issuesResponseData; + factory(); + + wrapper.vm.applyLabelFilter(label); + + expect(mockedFilteredSearch.clearSearch).toHaveBeenCalled(); + expect(mockedFilteredSearch.updateObject).toHaveBeenCalled(); + expect(mockedFilteredSearch.loadSearchParamsFromURL).toHaveBeenCalled(); + }); + + it('disables loading in issues dashboard page if assignee filter is incorrect', () => { + window.gon = { + current_username: 'not_root', + }; + + state.issues = []; + state.filters = '?assignee_username=root'; + factory( + {}, + { + data() { + return { + ISSUES_PER_PAGE: 20, + isInGroupsPage: false, + isInProjectPage: false, + isInDashboardPage: true, + isLoadingDisabled: false, + }; + }, + }, + ); + + expect(wrapper.vm.isLoadingDisabled).toBe(true); + }); + }); +}); diff --git a/spec/frontend/issues/mock_data.js b/spec/frontend/issues/mock_data.js new file mode 100644 index 00000000000..2a0f209336d --- /dev/null +++ b/spec/frontend/issues/mock_data.js @@ -0,0 +1,1491 @@ +export const issuesResponseData = [ + { + id: 389, + iid: 1, + project_id: 15, + title: 'Add Content', + description: 'Add content to this repo', + state: 'opened', + created_at: '2019-04-06T11:06:27.510Z', + updated_at: '2019-04-06T11:06:27.510Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: null, + assignees: [ + { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: + 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + ], + author: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + assignee: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + user_notes_count: 0, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: '2019-07-25', + confidential: true, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/awesome-jekyll/issues/1', + reference_path: '#1', + real_path: '/gitlab-org/awesome-jekyll/issues/1', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: 20, + }, + { + id: 246, + iid: 33, + project_id: 1, + title: 'Dismiss Cipher with no integrity', + description: null, + state: 'opened', + created_at: '2018-11-05T09:26:15.164Z', + updated_at: '2019-04-11T20:07:02.662Z', + closed_at: null, + closed_by: null, + labels: [ + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: null, + assignees: [], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: null, + user_notes_count: 2, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/33', + reference_path: '#33', + real_path: '/gitlab-org/gitlab-test/issues/33', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 245, + iid: 32, + project_id: 1, + title: 'Dismiss Cipher with no integrity', + description: + '* [ ] Do the first thing\n* [ ] Do the next thing\n* [ ] Do the third thing\n* [ ] Do the last thing', + state: 'opened', + created_at: '2018-11-05T09:26:15.103Z', + updated_at: '2019-04-12T05:43:47.971Z', + closed_at: null, + closed_by: null, + labels: [ + { + id: 38, + name: 'priority::1', + color: '#FF0000', + description: 'This is for top level issues that should we worked on first', + text_color: '#FFFFFF', + }, + ], + milestone: null, + assignees: [ + { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: + 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: + 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: + 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: + 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + { + id: 13, + name: 'Shannan Quigley', + username: 'alva_cassin', + state: 'active', + avatar_url: + 'http://test.host/avatar/8456544bf25a412a9c08f7b6c4e7fc62?s=80\u0026d=identicon', + web_url: 'http://test.host/alva_cassin', + }, + { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: + 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: + 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + ], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + user_notes_count: 3, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: true, + discussion_locked: null, + has_tasks: true, + task_status: '0 of 4 tasks completed', + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/32', + reference_path: '#32', + real_path: '/gitlab-org/gitlab-test/issues/32', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 244, + iid: 31, + project_id: 1, + title: 'Dismiss Cipher with no integrity', + description: null, + state: 'opened', + created_at: '2018-11-05T09:26:15.047Z', + updated_at: '2019-04-11T20:07:02.542Z', + closed_at: null, + closed_by: null, + labels: [ + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: null, + assignees: [], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: null, + user_notes_count: 0, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/31', + reference_path: '#31', + real_path: '/gitlab-org/gitlab-test/issues/31', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 20, + iid: 10, + project_id: 2, + title: 'Quo beatae ullam laborum est quisquam laudantium ut et autem mollitia.', + description: 'Eveniet voluptatem molestiae dolor expedita.', + state: 'opened', + created_at: '2018-11-05T09:21:13.533Z', + updated_at: '2019-03-29T08:32:36.294Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 6, + iid: 1, + project_id: 2, + title: 'v0.0', + description: 'Non nemo aut consequatur et recusandae.', + state: 'closed', + created_at: '2018-11-05T09:21:09.485Z', + updated_at: '2018-11-05T09:21:09.485Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/1', + }, + assignees: [ + { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: + 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + ], + author: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + assignee: { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + user_notes_count: 12, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/10', + reference_path: '#10', + real_path: '/gitlab-org/gitlab-shell/issues/10', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 19, + iid: 9, + project_id: 2, + title: 'Aliquam earum sit dolore voluptates assumenda autem omnis eum necessitatibus minus.', + description: 'Et qui atque deleniti nulla non sed provident ut.', + state: 'opened', + created_at: '2018-11-05T09:21:13.428Z', + updated_at: '2019-01-30T07:17:54.796Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 8, + iid: 3, + project_id: 2, + title: 'v2.0', + description: 'Debitis sit aut rerum voluptatem provident corporis sint.', + state: 'closed', + created_at: '2018-11-05T09:21:09.524Z', + updated_at: '2018-11-05T09:21:09.524Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/3', + }, + assignees: [ + { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: + 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + ], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/9', + reference_path: '#9', + real_path: '/gitlab-org/gitlab-shell/issues/9', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 17, + iid: 7, + project_id: 2, + title: 'Est nihil ut aut et excepturi ut.', + description: 'Est nesciunt dolor et similique porro ipsam libero.', + state: 'opened', + created_at: '2018-11-05T09:21:13.207Z', + updated_at: '2019-01-22T16:04:41.645Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 10, + iid: 5, + project_id: 2, + title: 'v4.0', + description: 'Ipsam amet possimus cupiditate fugit perferendis non enim eligendi.', + state: 'active', + created_at: '2018-11-05T09:21:09.562Z', + updated_at: '2018-11-05T09:21:09.562Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/5', + }, + assignees: [ + { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: + 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + ], + author: { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + assignee: { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + user_notes_count: 7, + merge_requests_count: 1, + upvotes: 0, + downvotes: 0, + due_date: '2018-11-09', + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/7', + reference_path: '#7', + real_path: '/gitlab-org/gitlab-shell/issues/7', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 16, + iid: 6, + project_id: 2, + title: 'Qui fuga esse explicabo facilis velit ad eius error mollitia sed.', + description: 'Architecto sed alias cum non incidunt et nemo minus.', + state: 'opened', + created_at: '2018-11-05T09:21:13.105Z', + updated_at: '2018-11-05T09:22:22.510Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 9, + iid: 4, + project_id: 2, + title: 'v3.0', + description: 'Omnis et non explicabo nostrum velit nihil.', + state: 'closed', + created_at: '2018-11-05T09:21:09.545Z', + updated_at: '2018-11-05T09:21:09.545Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/4', + }, + assignees: [ + { + id: 14, + name: 'Shantell Stokes', + username: 'chi', + state: 'active', + avatar_url: + 'http://test.host/avatar/a21b34070d1abbae545f302caeaca174?s=80\u0026d=identicon', + web_url: 'http://test.host/chi', + }, + ], + author: { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + assignee: { + id: 14, + name: 'Shantell Stokes', + username: 'chi', + state: 'active', + avatar_url: 'http://test.host/avatar/a21b34070d1abbae545f302caeaca174?s=80\u0026d=identicon', + web_url: 'http://test.host/chi', + }, + user_notes_count: 7, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/6', + reference_path: '#6', + real_path: '/gitlab-org/gitlab-shell/issues/6', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 15, + iid: 5, + project_id: 2, + title: 'Corrupti numquam in quibusdam sunt quia autem quam suscipit itaque.', + description: 'Vel officia esse quasi sunt.', + state: 'opened', + created_at: '2018-11-05T09:21:13.000Z', + updated_at: '2018-11-05T09:22:22.250Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 9, + iid: 4, + project_id: 2, + title: 'v3.0', + description: 'Omnis et non explicabo nostrum velit nihil.', + state: 'closed', + created_at: '2018-11-05T09:21:09.545Z', + updated_at: '2018-11-05T09:21:09.545Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/4', + }, + assignees: [ + { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: + 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + ], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + user_notes_count: 7, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/5', + reference_path: '#5', + real_path: '/gitlab-org/gitlab-shell/issues/5', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 12, + iid: 2, + project_id: 2, + title: 'Consequatur autem dolor facere architecto esse et delectus.', + description: 'Corporis esse ea iste incidunt porro ex qui.', + state: 'opened', + created_at: '2018-11-05T09:21:12.702Z', + updated_at: '2018-11-05T09:22:21.414Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 6, + iid: 1, + project_id: 2, + title: 'v0.0', + description: 'Non nemo aut consequatur et recusandae.', + state: 'closed', + created_at: '2018-11-05T09:21:09.485Z', + updated_at: '2018-11-05T09:21:09.485Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/1', + }, + assignees: [ + { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: + 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + ], + author: { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + assignee: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + user_notes_count: 7, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/2', + reference_path: '#2', + real_path: '/gitlab-org/gitlab-shell/issues/2', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 10, + iid: 10, + project_id: 1, + title: 'Asperiores rerum a ea ipsam cum explicabo aperiam deleniti et officia.', + description: 'Aperiam eum explicabo doloribus molestias nostrum ex labore consequatur.', + state: 'opened', + created_at: '2018-11-05T09:21:12.439Z', + updated_at: '2018-11-05T09:22:20.837Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 1, + iid: 1, + project_id: 1, + title: 'v0.0', + description: 'Eum laborum aut facilis qui voluptas est.', + state: 'closed', + created_at: '2018-11-05T09:21:09.381Z', + updated_at: '2018-11-05T09:21:09.381Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/1', + }, + assignees: [ + { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: + 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + ], + author: { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + assignee: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/10', + reference_path: '#10', + real_path: '/gitlab-org/gitlab-test/issues/10', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 8, + iid: 8, + project_id: 1, + title: 'Nihil inventore fugiat quibusdam dignissimos aperiam nemo ea dolor consequatur.', + description: 'Maxime doloremque quasi sapiente quos ex eligendi expedita id.', + state: 'opened', + created_at: '2018-11-05T09:21:12.240Z', + updated_at: '2019-04-11T20:07:02.265Z', + closed_at: null, + closed_by: null, + labels: [ + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: { + id: 2, + iid: 2, + project_id: 1, + title: 'v1.0', + description: 'Ut libero impedit perferendis et voluptate eos.', + state: 'active', + created_at: '2018-11-05T09:21:09.411Z', + updated_at: '2018-11-05T09:21:09.411Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/2', + }, + assignees: [ + { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: + 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + ], + author: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + assignee: { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/8', + reference_path: '#8', + real_path: '/gitlab-org/gitlab-test/issues/8', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 7, + iid: 7, + project_id: 1, + title: 'Sit ut ab commodi aut nulla veritatis corrupti velit pariatur sint.', + description: 'Reiciendis ab assumenda consequatur magni consequatur.', + state: 'opened', + created_at: '2018-11-05T09:21:12.109Z', + updated_at: '2019-04-11T20:07:02.115Z', + closed_at: null, + closed_by: null, + labels: [ + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: { + id: 2, + iid: 2, + project_id: 1, + title: 'v1.0', + description: 'Ut libero impedit perferendis et voluptate eos.', + state: 'active', + created_at: '2018-11-05T09:21:09.411Z', + updated_at: '2018-11-05T09:21:09.411Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/2', + }, + assignees: [ + { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: + 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + ], + author: { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + assignee: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/7', + reference_path: '#7', + real_path: '/gitlab-org/gitlab-test/issues/7', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 6, + iid: 6, + project_id: 1, + title: 'Sed autem non aut consequatur odio eveniet quidem omnis ea.', + description: 'Rerum eligendi sunt qui ducimus nihil modi quia deserunt.', + state: 'opened', + created_at: '2018-11-05T09:21:11.994Z', + updated_at: '2019-04-11T20:07:01.956Z', + closed_at: null, + closed_by: null, + labels: [ + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: { + id: 2, + iid: 2, + project_id: 1, + title: 'v1.0', + description: 'Ut libero impedit perferendis et voluptate eos.', + state: 'active', + created_at: '2018-11-05T09:21:09.411Z', + updated_at: '2018-11-05T09:21:09.411Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/2', + }, + assignees: [ + { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: + 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + ], + author: { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + assignee: { + id: 23, + name: 'User 1', + username: 'user1', + state: 'active', + avatar_url: 'http://test.host/avatar/111d68d06e2d317b5a59c2c6c5bad808?s=80\u0026d=identicon', + web_url: 'http://test.host/user1', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/6', + reference_path: '#6', + real_path: '/gitlab-org/gitlab-test/issues/6', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 5, + iid: 5, + project_id: 1, + title: 'Voluptas accusamus ut officiis ut voluptatem perspiciatis in eius dicta doloribus.', + description: 'Quibusdam cupiditate qui molestias autem aut voluptatem voluptatem mollitia.', + state: 'opened', + created_at: '2018-11-05T09:21:11.877Z', + updated_at: '2019-04-11T20:07:01.823Z', + closed_at: null, + closed_by: null, + labels: [ + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: { + id: 4, + iid: 4, + project_id: 1, + title: 'v3.0', + description: 'Tempore voluptatem corrupti a perspiciatis autem.', + state: 'active', + created_at: '2018-11-05T09:21:09.446Z', + updated_at: '2018-11-05T09:21:09.446Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/4', + }, + assignees: [ + { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: + 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + ], + author: { + id: 13, + name: 'Shannan Quigley', + username: 'alva_cassin', + state: 'active', + avatar_url: 'http://test.host/avatar/8456544bf25a412a9c08f7b6c4e7fc62?s=80\u0026d=identicon', + web_url: 'http://test.host/alva_cassin', + }, + assignee: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/5', + reference_path: '#5', + real_path: '/gitlab-org/gitlab-test/issues/5', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 4, + iid: 4, + project_id: 1, + title: 'Maxime ut repudiandae voluptatem libero nostrum iste aut deleniti consectetur.', + description: 'Non dolorem odio sed asperiores in.', + state: 'opened', + created_at: '2018-11-05T09:21:11.768Z', + updated_at: '2018-11-05T09:22:19.054Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 2, + iid: 2, + project_id: 1, + title: 'v1.0', + description: 'Ut libero impedit perferendis et voluptate eos.', + state: 'active', + created_at: '2018-11-05T09:21:09.411Z', + updated_at: '2018-11-05T09:21:09.411Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/2', + }, + assignees: [ + { + id: 13, + name: 'Shannan Quigley', + username: 'alva_cassin', + state: 'active', + avatar_url: + 'http://test.host/avatar/8456544bf25a412a9c08f7b6c4e7fc62?s=80\u0026d=identicon', + web_url: 'http://test.host/alva_cassin', + }, + ], + author: { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + assignee: { + id: 13, + name: 'Shannan Quigley', + username: 'alva_cassin', + state: 'active', + avatar_url: 'http://test.host/avatar/8456544bf25a412a9c08f7b6c4e7fc62?s=80\u0026d=identicon', + web_url: 'http://test.host/alva_cassin', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/4', + reference_path: '#4', + real_path: '/gitlab-org/gitlab-test/issues/4', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 1, + iid: 1, + project_id: 1, + title: 'Corrupti unde non aperiam id eligendi aut totam sit temporibus.', + description: 'Quia quasi dicta omnis qui.', + state: 'opened', + created_at: '2018-11-05T09:21:10.842Z', + updated_at: '2019-04-14T06:52:03.837Z', + closed_at: null, + closed_by: null, + labels: [ + { + id: 38, + name: 'priority::1', + color: '#FF0000', + description: 'This is for top level issues that should we worked on first', + text_color: '#FFFFFF', + }, + { id: 36, name: 'To Do', color: '#F0AD4E', description: null, text_color: '#FFFFFF' }, + { id: 37, name: 'Doing', color: '#5CB85C', description: null, text_color: '#FFFFFF' }, + ], + milestone: { + id: 2, + iid: 2, + project_id: 1, + title: 'v1.0', + description: 'Ut libero impedit perferendis et voluptate eos.', + state: 'active', + created_at: '2018-11-05T09:21:09.411Z', + updated_at: '2018-11-05T09:21:09.411Z', + due_date: null, + start_date: null, + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/2', + }, + assignees: [ + { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: + 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + ], + author: { + id: 7, + name: 'Minta Friesen', + username: 'irene_hickle', + state: 'active', + avatar_url: 'http://test.host/avatar/9231b409b04d59788caa3f1b69cab29e?s=80\u0026d=identicon', + web_url: 'http://test.host/irene_hickle', + }, + assignee: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + user_notes_count: 8, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/1', + reference_path: '#1', + real_path: '/gitlab-org/gitlab-test/issues/1', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 152, + iid: 22, + project_id: 2, + title: 'Quas saepe laboriosam cupiditate incidunt eos occaecati.', + description: 'Quo magni blanditiis et sunt omnis dolorem enim ipsa.', + state: 'opened', + created_at: '2018-10-26T09:25:35.917Z', + updated_at: '2019-01-16T12:36:49.591Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 44, + iid: 6, + project_id: 2, + title: 'Sprint - Animi necessitatibus sit laboriosam sequi eum voluptates id illum.', + description: 'Architecto quod animi officia quis quas minus quidem saepe.', + state: 'active', + created_at: '2018-10-26T09:25:34.584Z', + updated_at: '2018-10-26T09:25:34.584Z', + due_date: '2018-11-03', + start_date: '2018-10-26', + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/6', + }, + assignees: [ + { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: + 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + ], + author: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + assignee: { + id: 20, + name: 'Sharee Gerhold', + username: 'geri_waelchi', + state: 'active', + avatar_url: 'http://test.host/avatar/7cc8a4b30b2071494223297b9aadeaec?s=80\u0026d=identicon', + web_url: 'http://test.host/geri_waelchi', + }, + user_notes_count: 0, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/22', + reference_path: '#22', + real_path: '/gitlab-org/gitlab-shell/issues/22', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 151, + iid: 21, + project_id: 2, + title: 'Ad dolorem nobis et nulla tempore qui itaque provident eos et.', + description: 'Laboriosam enim et ipsam explicabo.', + state: 'opened', + created_at: '2018-10-26T09:25:35.807Z', + updated_at: '2019-01-16T12:36:49.644Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 44, + iid: 6, + project_id: 2, + title: 'Sprint - Animi necessitatibus sit laboriosam sequi eum voluptates id illum.', + description: 'Architecto quod animi officia quis quas minus quidem saepe.', + state: 'active', + created_at: '2018-10-26T09:25:34.584Z', + updated_at: '2018-10-26T09:25:34.584Z', + due_date: '2018-11-03', + start_date: '2018-10-26', + web_url: 'http://test.host/gitlab-org/gitlab-shell/milestones/6', + }, + assignees: [ + { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: + 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + ], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: { + id: 10, + name: 'George Bartell', + username: 'jaimee', + state: 'active', + avatar_url: 'http://test.host/avatar/b8b798fad1dd688ceab20efff7624a74?s=80\u0026d=identicon', + web_url: 'http://test.host/jaimee', + }, + user_notes_count: 0, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-shell/issues/21', + reference_path: '#21', + real_path: '/gitlab-org/gitlab-shell/issues/21', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, + { + id: 119, + iid: 29, + project_id: 1, + title: 'Eaque minima culpa illo explicabo porro aut.', + description: 'Accusantium necessitatibus molestiae et quia animi.', + state: 'opened', + created_at: '2018-10-26T09:25:27.248Z', + updated_at: '2018-10-26T09:25:27.248Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: { + id: 42, + iid: 6, + project_id: 1, + title: 'Sprint - Delectus quasi accusamus dicta exercitationem.', + description: 'Corrupti recusandae in molestiae porro quae qui.', + state: 'active', + created_at: '2018-10-26T09:25:25.177Z', + updated_at: '2018-10-26T09:25:25.177Z', + due_date: '2018-11-03', + start_date: '2018-10-26', + web_url: 'http://test.host/gitlab-org/gitlab-test/milestones/6', + }, + assignees: [ + { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: + 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + ], + author: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + assignee: { + id: 2, + name: 'Wai Hamill', + username: 'felicia_tremblay', + state: 'active', + avatar_url: 'http://test.host/avatar/b53d4d33fdc1d0f9296e3440e71d1bde?s=80\u0026d=identicon', + web_url: 'http://test.host/felicia_tremblay', + }, + user_notes_count: 0, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: null, + confidential: false, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/gitlab-test/issues/29', + reference_path: '#29', + real_path: '/gitlab-org/gitlab-test/issues/29', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: null, + }, +]; + +export const singleIssueData = { + id: 389, + iid: 1, + project_id: 15, + title: 'Add Content', + description: 'Add content to this repo', + state: 'opened', + created_at: '2019-04-06T11:06:27.510Z', + updated_at: '2019-04-06T11:06:27.510Z', + closed_at: null, + closed_by: null, + labels: [], + milestone: null, + assignees: [ + { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + ], + author: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + assignee: { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: 'http://test.host/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://test.host/root', + }, + user_notes_count: 0, + merge_requests_count: 0, + upvotes: 0, + downvotes: 0, + due_date: '2019-07-25', + confidential: true, + discussion_locked: null, + has_tasks: false, + web_url: 'http://test.host/gitlab-org/awesome-jekyll/issues/1', + reference_path: '#1', + real_path: '/gitlab-org/awesome-jekyll/issues/1', + time_stats: { + time_estimate: 0, + total_time_spent: 0, + human_time_estimate: null, + human_total_time_spent: null, + }, + weight: 20, +}; diff --git a/spec/frontend/issues/stores/modules/issues_list/actions_spec.js b/spec/frontend/issues/stores/modules/issues_list/actions_spec.js new file mode 100644 index 00000000000..9c5cee9d955 --- /dev/null +++ b/spec/frontend/issues/stores/modules/issues_list/actions_spec.js @@ -0,0 +1,111 @@ +import MockAdapter from 'axios-mock-adapter'; +import statusCodes from '~/lib/utils/http_status'; +import axios from '~/lib/utils/axios_utils'; +import * as issuesActions from '~/issues/stores/modules/issues_list/actions'; +import * as types from '~/issues/stores/modules/issues_list/mutation_types'; +import testAction from '../../../../helpers/vuex_action_helper'; +import { issuesResponseData } from '../../../mock_data'; +import { setWindowLocation } from '../../../../helpers/url_util_helper'; + +describe('Issues List Actions', () => { + it('Should set filter value', done => { + const issueFilter = 'hello=world'; + + testAction( + issuesActions.setFilters, + issueFilter, + {}, + [{ type: types.SET_FILTERS, payload: issueFilter }], + [], + done, + ); + }); + + it('Should set loading state', done => { + const loadingState = 'loading'; + + testAction( + issuesActions.setLoadingState, + loadingState, + {}, + [{ type: types.SET_LOADING_STATE, payload: loadingState }], + [], + done, + ); + }); + + it('Should set bulk update state', done => { + const bulkUpdateState = 'updating'; + + testAction( + issuesActions.setBulkUpdateState, + bulkUpdateState, + {}, + [{ type: types.SET_BULK_UPDATE_STATE, payload: bulkUpdateState }], + [], + done, + ); + }); + + it('Should set current page', done => { + const currentPage = 1; + + testAction( + issuesActions.setCurrentPage, + currentPage, + {}, + [{ type: types.SET_CURRENT_PAGE, payload: currentPage }], + [], + done, + ); + }); + + it('Should set total Items', done => { + const totalItems = 200; + + testAction( + issuesActions.setTotalItems, + totalItems, + {}, + [{ type: types.SET_TOTAL_ITEMS, payload: totalItems }], + [], + done, + ); + }); + + it('should fetch issues', done => { + const totalIssues = 1000; + const currentPage = 1; + const issuesEndpoint = '/issues'; + const appliedFilters = 'scope=all&utf8=%E2%9C%93&state=opened&page=2'; + const mock = new MockAdapter(axios); + const { search } = window.location; + + mock.onGet(issuesEndpoint).reply(statusCodes.OK, JSON.stringify({ ...issuesResponseData }), { + 'x-total': totalIssues, + 'x-page': currentPage, + }); + + setWindowLocation({ + search: `?${appliedFilters}`, + }); + + testAction( + issuesActions.fetchIssues, + issuesEndpoint, + { appliedFilters }, + [{ type: types.SET_ISSUES_DATA, payload: { ...issuesResponseData } }], + [ + { type: 'setLoadingState', payload: true }, + { type: 'setTotalItems', payload: totalIssues }, + { type: 'setCurrentPage', payload: currentPage }, + { type: 'setLoadingState', payload: false }, + ], + () => { + mock.restore(); + window.location.search = search; + done(); + }, + ); + }); +}); diff --git a/spec/frontend/issues/stores/modules/issues_list/getters_spec.js b/spec/frontend/issues/stores/modules/issues_list/getters_spec.js new file mode 100644 index 00000000000..f68615fdbe8 --- /dev/null +++ b/spec/frontend/issues/stores/modules/issues_list/getters_spec.js @@ -0,0 +1,27 @@ +import state from '~/issues/stores/modules/issues_list/state'; +import { hasFilters } from '~/issues/stores/modules/issues_list/getters'; + +describe('Issue List Getters', () => { + let mockedState; + + beforeEach(() => { + mockedState = state(); + }); + + describe('hasFilters', () => { + it('should return "true" if current filters match issues filtered search tokens', () => { + mockedState.filters = '?state=opened&label_name[]=Doing'; + expect(hasFilters(mockedState)).toEqual(true); + }); + + it('should return "false" if current filters dont match issues filtered search tokens', () => { + mockedState.filters = '?scope=all&utf8=✓&state=opened'; + expect(hasFilters(mockedState)).toEqual(false); + }); + + it('should return "false" if there are no filters', () => { + mockedState.filters = ''; + expect(hasFilters(mockedState)).toEqual(false); + }); + }); +}); diff --git a/spec/frontend/issues/stores/modules/issues_list/mutations_spec.js b/spec/frontend/issues/stores/modules/issues_list/mutations_spec.js new file mode 100644 index 00000000000..15f9b07d1b1 --- /dev/null +++ b/spec/frontend/issues/stores/modules/issues_list/mutations_spec.js @@ -0,0 +1,66 @@ +import state from '~/issues/stores/modules/issues_list/state'; +import mutations from '~/issues/stores/modules/issues_list/mutations'; +import * as types from '~/issues/stores/modules/issues_list/mutation_types'; + +describe('Issues List Mutataions', () => { + let mockedState; + + beforeEach(() => { + mockedState = state(); + }); + + describe('SET_LOADING_STATE', () => { + it('sets the current loading state', () => { + mockedState.loading = false; + mutations[types.SET_LOADING_STATE](mockedState, true); + + expect(mockedState.loading).toEqual(true); + }); + }); + + describe('SET_FILTERS', () => { + it('sets the current filters', () => { + const mokedFilter = '?hello=worls'; + mockedState.filters = 'none'; + mutations[types.SET_FILTERS](mockedState, mokedFilter); + + expect(mockedState.filters).toEqual(mokedFilter); + }); + }); + + describe('SET_BULK_UPDATE_STATE', () => { + it('updates bulk update status', () => { + mockedState.isBulkUpdating = false; + mutations[types.SET_BULK_UPDATE_STATE](mockedState, true); + + expect(mockedState.isBulkUpdating).toEqual(true); + }); + }); + + describe('SET_TOTAL_ITEMS', () => { + it('sets the count of issues for pagination', () => { + mockedState.totalItems = 0; + mutations[types.SET_TOTAL_ITEMS](mockedState, '10'); + + expect(mockedState.totalItems).toEqual(10); + }); + }); + + describe('SET_CURRENT_PAGE', () => { + it('sets the current page value', () => { + mockedState.currentPage = 0; + mutations[types.SET_CURRENT_PAGE](mockedState, '1'); + + expect(mockedState.currentPage).toEqual(1); + }); + }); + + describe('SET_ISSUES_DATA', () => { + it('sets the current page value', () => { + mockedState.issues = null; + mutations[types.SET_ISSUES_DATA](mockedState, []); + + expect(mockedState.issues).toEqual([]); + }); + }); +}); diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js index a986bc49f28..dbab2822a0e 100644 --- a/spec/frontend/lib/utils/url_utility_spec.js +++ b/spec/frontend/lib/utils/url_utility_spec.js @@ -1,11 +1,5 @@ import * as urlUtils from '~/lib/utils/url_utility'; - -const setWindowLocation = value => { - Object.defineProperty(window, 'location', { - writable: true, - value, - }); -}; +import { setWindowLocation } from '../../helpers/url_util_helper'; describe('URL utility', () => { describe('webIDEUrl', () => { |