123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830 |
- import {browserHistory} from 'react-router';
- import cloneDeep from 'lodash/cloneDeep';
- import range from 'lodash/range';
- import {mountWithTheme, shallow} from 'sentry-test/enzyme';
- import {initializeOrg} from 'sentry-test/initializeOrg';
- import ErrorRobot from 'app/components/errorRobot';
- import StreamGroup from 'app/components/stream/group';
- import GroupStore from 'app/stores/groupStore';
- import TagStore from 'app/stores/tagStore';
- import * as parseLinkHeader from 'app/utils/parseLinkHeader';
- import IssueListWithStores, {IssueListOverview} from 'app/views/issueList/overview';
- // Mock <IssueListSidebar> and <IssueListActions>
- jest.mock('app/views/issueList/sidebar', () => jest.fn(() => null));
- jest.mock('app/views/issueList/actions', () => jest.fn(() => null));
- jest.mock('app/components/stream/group', () => jest.fn(() => null));
- jest.mock('app/views/issueList/noGroupsHandler/congratsRobots', () =>
- jest.fn(() => null)
- );
- const DEFAULT_LINKS_HEADER =
- '<http://127.0.0.1:8000/api/0/organizations/org-slug/issues/?cursor=1443575731:0:1>; rel="previous"; results="false"; cursor="1443575731:0:1", ' +
- '<http://127.0.0.1:8000/api/0/organizations/org-slug/issues/?cursor=1443575000:0:0>; rel="next"; results="true"; cursor="1443575000:0:0"';
- describe('IssueList', function () {
- let wrapper;
- let props;
- let organization;
- let project;
- let group;
- let groupStats;
- let savedSearch;
- let fetchTagsRequest;
- let fetchMembersRequest;
- const api = new MockApiClient();
- beforeEach(function () {
- MockApiClient.clearMockResponses();
- project = TestStubs.ProjectDetails({
- id: '3559',
- name: 'Foo Project',
- slug: 'project-slug',
- firstEvent: true,
- });
- organization = TestStubs.Organization({
- id: '1337',
- slug: 'org-slug',
- access: ['releases'],
- features: [],
- projects: [project],
- });
- savedSearch = TestStubs.Search({
- id: '789',
- query: 'is:unresolved',
- sort: 'date',
- name: 'Unresolved Issues',
- projectId: project.id,
- });
- group = TestStubs.Group({project});
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/issues/',
- body: [group],
- headers: {
- Link: DEFAULT_LINKS_HEADER,
- },
- });
- groupStats = TestStubs.GroupStats();
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/issues-stats/',
- body: [groupStats],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [savedSearch],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/recent-searches/',
- body: [],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/recent-searches/',
- method: 'POST',
- body: [],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/processingissues/',
- method: 'GET',
- body: [
- {
- project: 'test-project',
- numIssues: 1,
- hasIssues: true,
- lastSeen: '2019-01-16T15:39:11.081Z',
- },
- ],
- });
- const tags = TestStubs.Tags();
- fetchTagsRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/tags/',
- method: 'GET',
- body: tags,
- });
- fetchMembersRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/users/',
- method: 'GET',
- body: [TestStubs.Member({projects: [project.slug]})],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/sent-first-event/',
- body: {sentFirstEvent: true},
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: [project],
- });
- TagStore.init();
- props = {
- api,
- savedSearchLoading: false,
- savedSearches: [savedSearch],
- useOrgSavedSearches: true,
- selection: {
- projects: [parseInt(organization.projects[0].id, 10)],
- environments: [],
- datetime: {period: '14d'},
- },
- location: {query: {query: 'is:unresolved'}, search: 'query=is:unresolved'},
- params: {orgId: organization.slug},
- organization,
- tags: tags.reduce((acc, tag) => {
- acc[tag.key] = tag;
- return acc;
- }),
- };
- });
- afterEach(function () {
- jest.clearAllMocks();
- MockApiClient.clearMockResponses();
- if (wrapper) {
- wrapper.unmount();
- }
- wrapper = null;
- });
- describe('withStores and feature flags', function () {
- const {router, routerContext} = initializeOrg({
- organization: {
- features: ['global-views'],
- slug: 'org-slug',
- },
- router: {
- location: {query: {}, search: ''},
- params: {orgId: 'org-slug'},
- },
- });
- const defaultProps = {};
- let savedSearchesRequest;
- let recentSearchesRequest;
- let issuesRequest;
- /* helpers */
- const getSavedSearchTitle = w =>
- w.find('SavedSearchSelector DropdownMenu ButtonTitle').text();
- const getSearchBarValue = w =>
- w.find('SmartSearchBarContainer textarea').prop('value').trim();
- const createWrapper = ({params, location, ...p} = {}) => {
- const newRouter = {
- ...router,
- params: {
- ...router.params,
- ...params,
- },
- location: {
- ...router.location,
- ...location,
- },
- };
- wrapper = mountWithTheme(
- <IssueListWithStores {...newRouter} {...defaultProps} {...p} />,
- routerContext
- );
- };
- beforeEach(function () {
- StreamGroup.mockClear();
- recentSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/recent-searches/',
- method: 'GET',
- body: [],
- });
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [savedSearch],
- });
- issuesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/issues/',
- body: [group],
- headers: {
- Link: DEFAULT_LINKS_HEADER,
- },
- });
- });
- it('loads group rows with default query (no pinned queries, and no query in URL)', async function () {
- createWrapper();
- // Loading saved searches
- expect(savedSearchesRequest).toHaveBeenCalledTimes(1);
- // Update stores with saved searches
- await tick();
- await tick();
- wrapper.update();
- // auxillary requests being made
- expect(recentSearchesRequest).toHaveBeenCalledTimes(1);
- expect(fetchTagsRequest).toHaveBeenCalledTimes(1);
- expect(fetchMembersRequest).toHaveBeenCalledTimes(1);
- // primary /issues/ request
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with default query
- data: expect.stringContaining('is%3Aunresolved'),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('is:unresolved');
- // Organization saved search selector should have default saved search selected
- expect(getSavedSearchTitle(wrapper)).toBe('Unresolved Issues');
- // This is mocked
- expect(StreamGroup).toHaveBeenCalled();
- });
- it('loads with query in URL and pinned queries', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- savedSearch,
- TestStubs.Search({
- id: '123',
- name: 'My Pinned Search',
- isPinned: true,
- query: 'is:resolved',
- }),
- ],
- });
- createWrapper({
- location: {
- query: {
- query: 'level:foo',
- },
- },
- });
- // Update stores with saved searches
- await tick();
- await tick();
- wrapper.update();
- // Main /issues/ request
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with default query
- data: expect.stringContaining('level%3Afoo'),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('level:foo');
- // Custom search
- expect(getSavedSearchTitle(wrapper)).toBe('Custom Search');
- });
- it('loads with a pinned saved query', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- savedSearch,
- TestStubs.Search({
- id: '123',
- name: 'Org Custom',
- isPinned: true,
- isGlobal: false,
- isOrgCustom: true,
- query: 'is:resolved',
- }),
- ],
- });
- createWrapper();
- await tick();
- await tick();
- wrapper.update();
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with default query
- data: expect.stringContaining('is%3Aresolved'),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('is:resolved');
- // Organization saved search selector should have default saved search selected
- expect(getSavedSearchTitle(wrapper)).toBe('Org Custom');
- });
- it('loads with a pinned custom query', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- savedSearch,
- TestStubs.Search({
- id: '123',
- name: 'My Pinned Search',
- isPinned: true,
- isGlobal: false,
- isOrgCustom: false,
- query: 'is:resolved',
- }),
- ],
- });
- createWrapper();
- await tick();
- await tick();
- wrapper.update();
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with default query
- data: expect.stringContaining('is%3Aresolved'),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('is:resolved');
- // Organization saved search selector should have default saved search selected
- expect(getSavedSearchTitle(wrapper)).toBe('My Pinned Search');
- });
- it('loads with a saved query', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- TestStubs.Search({
- id: '123',
- name: 'Assigned to Me',
- isPinned: false,
- isGlobal: true,
- query: 'assigned:me',
- sort: 'priority',
- projectId: null,
- type: 0,
- }),
- ],
- });
- createWrapper({params: {searchId: '123'}});
- await tick();
- await tick();
- wrapper.update();
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with default query
- data:
- expect.stringContaining('assigned%3Ame') &&
- expect.stringContaining('sort=priority'),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('assigned:me');
- // Organization saved search selector should have default saved search selected
- expect(getSavedSearchTitle(wrapper)).toBe('Assigned to Me');
- });
- it('loads with a query in URL', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- TestStubs.Search({
- id: '123',
- name: 'Assigned to Me',
- isPinned: false,
- isGlobal: true,
- query: 'assigned:me',
- projectId: null,
- type: 0,
- }),
- ],
- });
- createWrapper({location: {query: {query: 'level:error'}}});
- await tick();
- await tick();
- wrapper.update();
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with default query
- data: expect.stringContaining('level%3Aerror'),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('level:error');
- // Organization saved search selector should have default saved search selected
- expect(getSavedSearchTitle(wrapper)).toBe('Custom Search');
- });
- it('loads with an empty query in URL', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- TestStubs.Search({
- id: '123',
- name: 'My Pinned Search',
- isPinned: true,
- isGlobal: false,
- isOrgCustom: false,
- query: 'is:resolved',
- }),
- ],
- });
- createWrapper({location: {query: {query: undefined}}});
- await tick();
- await tick();
- wrapper.update();
- expect(issuesRequest).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- // Should be called with empty query
- data: expect.stringContaining(''),
- })
- );
- expect(getSearchBarValue(wrapper)).toBe('is:resolved');
- // Organization saved search selector should have default saved search selected
- expect(getSavedSearchTitle(wrapper)).toBe('My Pinned Search');
- });
- it('selects a saved search and changes sort', async function () {
- const localSavedSearch = {...savedSearch, projectId: null};
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [localSavedSearch],
- });
- createWrapper();
- await tick();
- await tick();
- wrapper.update();
- wrapper.find('SavedSearchSelector DropdownButton').simulate('click');
- wrapper.find('SavedSearchSelector MenuItem a').first().simulate('click');
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/789/',
- })
- );
- // Need to update component
- wrapper.setProps({
- savedSearch: localSavedSearch,
- location: {
- ...router.location,
- pathname: '/organizations/org-slug/issues/searches/789/',
- query: {
- sort: 'freq',
- environment: [],
- project: [],
- },
- },
- });
- await tick();
- wrapper.update();
- wrapper.find('IssueListSortOptions DropdownButton').simulate('click');
- wrapper.find('DropdownItem').at(3).find('MenuItem span').at(1).simulate('click');
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/789/',
- query: {
- environment: [],
- project: [],
- sort: 'freq',
- statsPeriod: '14d',
- },
- })
- );
- });
- it('clears a saved search when a custom one is entered', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [
- savedSearch,
- TestStubs.Search({
- id: '123',
- name: 'Pinned search',
- isPinned: true,
- isGlobal: false,
- isOrgCustom: true,
- query: 'is:resolved',
- }),
- ],
- });
- createWrapper();
- await tick();
- await tick();
- await wrapper.update();
- // Update the search textarea
- wrapper
- .find('IssueListFilters SmartSearchBar textarea')
- .simulate('change', {target: {value: 'dogs'}});
- // Submit the form
- wrapper.find('IssueListFilters SmartSearchBar form').simulate('submit');
- await wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/',
- query: {
- environment: [],
- project: [],
- query: 'dogs',
- statsPeriod: '14d',
- },
- })
- );
- });
- it('pins and unpins a custom query', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [savedSearch],
- });
- createWrapper();
- await tick();
- await tick();
- wrapper.update();
- const createPin = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/pinned-searches/',
- method: 'PUT',
- body: {
- ...savedSearch,
- id: '666',
- name: 'My Pinned Search',
- query: 'assigned:me level:fatal',
- sort: 'date',
- isPinned: true,
- },
- });
- const deletePin = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/pinned-searches/',
- method: 'DELETE',
- });
- wrapper
- .find('SmartSearchBar textarea')
- .simulate('change', {target: {value: 'assigned:me level:fatal'}});
- wrapper.find('SmartSearchBar form').simulate('submit');
- expect(browserHistory.push.mock.calls[0][0]).toEqual(
- expect.objectContaining({
- query: expect.objectContaining({
- query: 'assigned:me level:fatal',
- }),
- })
- );
- await tick();
- wrapper.setProps({
- location: {
- ...router.location,
- query: {
- query: 'assigned:me level:fatal',
- },
- },
- });
- expect(wrapper.find('SavedSearchSelector ButtonTitle').text()).toBe(
- 'Custom Search'
- );
- wrapper.find('Button[aria-label="Pin this search"] button').simulate('click');
- expect(createPin).toHaveBeenCalled();
- await tick();
- wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/666/',
- query: {},
- search: '',
- })
- );
- wrapper.setProps({
- params: {
- ...router.params,
- searchId: '666',
- },
- });
- await tick();
- wrapper.update();
- expect(wrapper.find('SavedSearchSelector ButtonTitle').text()).toBe(
- 'My Pinned Search'
- );
- wrapper.find('Button[aria-label="Unpin this search"] button').simulate('click');
- expect(deletePin).toHaveBeenCalled();
- await tick();
- wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/',
- query: {
- query: 'assigned:me level:fatal',
- sort: 'date',
- },
- })
- );
- });
- it('pins and unpins a saved query', async function () {
- const assignedToMe = TestStubs.Search({
- id: '234',
- name: 'Assigned to Me',
- isPinned: false,
- isGlobal: true,
- query: 'assigned:me',
- sort: 'date',
- projectId: null,
- type: 0,
- });
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [savedSearch, assignedToMe],
- });
- createWrapper();
- await tick();
- await tick();
- wrapper.update();
- let createPin = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/pinned-searches/',
- method: 'PUT',
- body: {
- ...savedSearch,
- isPinned: true,
- },
- });
- wrapper.find('SavedSearchSelector DropdownButton').simulate('click');
- wrapper.find('SavedSearchSelector MenuItem a').first().simulate('click');
- await tick();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/789/',
- query: {
- environment: [],
- project: ['3559'],
- statsPeriod: '14d',
- sort: 'date',
- },
- })
- );
- wrapper.setProps({
- params: {
- ...router.params,
- searchId: '789',
- },
- });
- expect(wrapper.find('SavedSearchSelector ButtonTitle').text()).toBe(
- 'Unresolved Issues'
- );
- wrapper.find('Button[aria-label="Pin this search"] button').simulate('click');
- expect(createPin).toHaveBeenCalled();
- await tick();
- wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/789/',
- })
- );
- wrapper.setProps({
- params: {
- ...router.params,
- searchId: '789',
- },
- });
- await tick();
- wrapper.update();
- expect(wrapper.find('SavedSearchSelector ButtonTitle').text()).toBe(
- 'Unresolved Issues'
- );
- // Select other saved search
- wrapper.find('SavedSearchSelector DropdownButton').simulate('click');
- wrapper.find('SavedSearchSelector MenuItem a').at(1).simulate('click');
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/234/',
- query: {
- project: [],
- environment: [],
- statsPeriod: '14d',
- sort: 'date',
- },
- })
- );
- wrapper.setProps({
- params: {
- ...router.params,
- searchId: '234',
- },
- });
- expect(wrapper.find('SavedSearchSelector ButtonTitle').text()).toBe(
- 'Assigned to Me'
- );
- createPin = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/pinned-searches/',
- method: 'PUT',
- body: {
- ...assignedToMe,
- isPinned: true,
- },
- });
- wrapper.find('Button[aria-label="Pin this search"] button').simulate('click');
- expect(createPin).toHaveBeenCalled();
- await tick();
- wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/234/',
- })
- );
- wrapper.setProps({
- params: {
- ...router.params,
- searchId: '234',
- },
- });
- await tick();
- wrapper.update();
- expect(wrapper.find('SavedSearchSelector ButtonTitle').text()).toBe(
- 'Assigned to Me'
- );
- });
- it('pinning and unpinning searches should keep project selected', async function () {
- savedSearchesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/searches/',
- body: [savedSearch],
- });
- createWrapper({
- selection: {
- projects: [123],
- environments: ['prod'],
- datetime: {},
- },
- location: {query: {project: ['123'], environment: ['prod']}},
- });
- await tick();
- await tick();
- wrapper.update();
- const deletePin = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/pinned-searches/',
- method: 'DELETE',
- });
- const createPin = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/pinned-searches/',
- method: 'PUT',
- body: {
- ...savedSearch,
- id: '666',
- name: 'My Pinned Search',
- query: 'assigned:me level:fatal',
- sort: 'date',
- isPinned: true,
- },
- });
- wrapper
- .find('SmartSearchBar textarea')
- .simulate('change', {target: {value: 'assigned:me level:fatal'}});
- wrapper.find('SmartSearchBar form').simulate('submit');
- await tick();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- query: expect.objectContaining({
- project: [123],
- environment: ['prod'],
- query: 'assigned:me level:fatal',
- }),
- })
- );
- const newRouter = {
- ...router,
- location: {
- ...router.location,
- query: {
- ...router.location.query,
- project: [123],
- environment: ['prod'],
- query: 'assigned:me level:fatal',
- },
- },
- };
- wrapper.setProps({...newRouter, router: newRouter});
- wrapper.setContext({router: newRouter});
- wrapper.update();
- wrapper.find('Button[aria-label="Pin this search"] button').simulate('click');
- expect(createPin).toHaveBeenCalled();
- await tick();
- wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/searches/666/',
- query: expect.objectContaining({
- project: [123],
- environment: ['prod'],
- query: 'assigned:me level:fatal',
- }),
- })
- );
- wrapper.setProps({
- params: {
- ...router.params,
- searchId: '666',
- },
- });
- await tick();
- wrapper.update();
- wrapper.find('Button[aria-label="Unpin this search"] button').simulate('click');
- expect(deletePin).toHaveBeenCalled();
- await tick();
- wrapper.update();
- expect(browserHistory.push).toHaveBeenLastCalledWith(
- expect.objectContaining({
- pathname: '/organizations/org-slug/issues/',
- query: expect.objectContaining({
- project: [123],
- environment: ['prod'],
- query: 'assigned:me level:fatal',
- }),
- })
- );
- });
- it.todo('saves a new query');
- it.todo('loads pinned search when invalid saved search id is accessed');
- it('does not allow pagination to "previous" while on first page and resets cursors when navigating back to initial page', async function () {
- let pushArgs;
- createWrapper();
- await tick();
- await tick();
- wrapper.update();
- expect(wrapper.find('Pagination Button').first().prop('disabled')).toBe(true);
- issuesRequest = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/issues/',
- body: [group],
- headers: {
- Link:
- '<http://127.0.0.1:8000/api/0/organizations/org-slug/issues/?cursor=1443575000:0:0>; rel="previous"; results="true"; cursor="1443575000:0:1", <http://127.0.0.1:8000/api/0/organizations/org-slug/issues/?cursor=1443574000:0:0>; rel="next"; results="true"; cursor="1443574000:0:0"',
- },
- });
- // Click next
- wrapper.find('Pagination Button').last().simulate('click');
- await tick();
- pushArgs = {
- pathname: '/organizations/org-slug/issues/',
- query: {
- cursor: '1443575000:0:0',
- page: 1,
- environment: [],
- project: [],
- query: 'is:unresolved',
- statsPeriod: '14d',
- },
- };
- expect(browserHistory.push).toHaveBeenLastCalledWith(pushArgs);
- wrapper.setProps({location: pushArgs});
- wrapper.setContext({location: pushArgs});
- expect(wrapper.find('Pagination Button').first().prop('disabled')).toBe(false);
- // Click next again
- wrapper.find('Pagination Button').last().simulate('click');
- await tick();
- pushArgs = {
- pathname: '/organizations/org-slug/issues/',
- query: {
- cursor: '1443574000:0:0',
- page: 2,
- environment: [],
- project: [],
- query: 'is:unresolved',
- statsPeriod: '14d',
- },
- };
- expect(browserHistory.push).toHaveBeenLastCalledWith(pushArgs);
- wrapper.setProps({location: pushArgs});
- wrapper.setContext({location: pushArgs});
- // Click previous
- wrapper.find('Pagination Button').first().simulate('click');
- await tick();
- pushArgs = {
- pathname: '/organizations/org-slug/issues/',
- query: {
- cursor: '1443575000:0:1',
- page: 1,
- environment: [],
- project: [],
- query: 'is:unresolved',
- statsPeriod: '14d',
- },
- };
- expect(browserHistory.push).toHaveBeenLastCalledWith(pushArgs);
- wrapper.setProps({location: pushArgs});
- wrapper.setContext({location: pushArgs});
- // Click previous back to initial page
- wrapper.find('Pagination Button').first().simulate('click');
- await tick();
- // cursor is undefined because "prev" cursor is === initial "next" cursor
- expect(browserHistory.push).toHaveBeenLastCalledWith({
- pathname: '/organizations/org-slug/issues/',
- query: {
- cursor: undefined,
- environment: [],
- page: undefined,
- project: [],
- query: 'is:unresolved',
- statsPeriod: '14d',
- },
- });
- });
- });
- describe('transitionTo', function () {
- let instance;
- beforeEach(function () {
- wrapper = shallow(<IssueListOverview {...props} />);
- instance = wrapper.instance();
- });
- it('transitions to query updates', function () {
- instance.transitionTo({query: 'is:ignored'});
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/',
- query: {
- environment: [],
- project: [parseInt(project.id, 10)],
- query: 'is:ignored',
- statsPeriod: '14d',
- },
- });
- });
- it('transitions to cursor with project-less saved search', function () {
- savedSearch = {
- id: 123,
- projectId: null,
- query: 'foo:bar',
- };
- instance.transitionTo({cursor: '1554756114000:0:0'}, savedSearch);
- // should keep the current project selection as we're going to the next page.
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/searches/123/',
- query: {
- environment: [],
- project: [parseInt(project.id, 10)],
- cursor: '1554756114000:0:0',
- statsPeriod: '14d',
- },
- });
- });
- it('transitions to cursor with project saved search', function () {
- savedSearch = {
- id: 123,
- projectId: 999,
- query: 'foo:bar',
- };
- instance.transitionTo({cursor: '1554756114000:0:0'}, savedSearch);
- // should keep the current project selection as we're going to the next page.
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/searches/123/',
- query: {
- environment: [],
- project: [parseInt(project.id, 10)],
- cursor: '1554756114000:0:0',
- statsPeriod: '14d',
- },
- });
- });
- it('transitions to saved search that has a projectId', function () {
- savedSearch = {
- id: 123,
- projectId: 99,
- query: 'foo:bar',
- };
- instance.transitionTo(undefined, savedSearch);
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/searches/123/',
- query: {
- environment: [],
- project: [savedSearch.projectId],
- statsPeriod: '14d',
- },
- });
- });
- it('transitions to saved search with a sort', function () {
- savedSearch = {
- id: 123,
- project: null,
- query: 'foo:bar',
- sort: 'freq',
- };
- instance.transitionTo(undefined, savedSearch);
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/searches/123/',
- query: {
- environment: [],
- project: [parseInt(project.id, 10)],
- statsPeriod: '14d',
- sort: savedSearch.sort,
- },
- });
- });
- it('goes to all projects when using a basic saved search and global-views feature', function () {
- organization.features = ['global-views'];
- savedSearch = {
- id: 1,
- project: null,
- query: 'is:unresolved',
- };
- instance.transitionTo(undefined, savedSearch);
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/searches/1/',
- query: {
- project: [parseInt(project.id, 10)],
- environment: [],
- statsPeriod: '14d',
- },
- });
- });
- it('retains project selection when using a basic saved search and no global-views feature', function () {
- organization.features = [];
- savedSearch = {
- id: 1,
- projectId: null,
- query: 'is:unresolved',
- };
- instance.transitionTo(undefined, savedSearch);
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/issues/searches/1/',
- query: {
- environment: [],
- project: props.selection.projects,
- statsPeriod: '14d',
- },
- });
- });
- });
- describe('getEndpointParams', function () {
- beforeEach(function () {
- wrapper = shallow(<IssueListOverview {...props} />);
- });
- it('omits null values', function () {
- wrapper.setProps({
- selection: {
- projects: null,
- environments: null,
- datetime: {period: '14d'},
- },
- });
- const value = wrapper.instance().getEndpointParams();
- expect(value.project).toBeUndefined();
- expect(value.projects).toBeUndefined();
- expect(value.environment).toBeUndefined();
- expect(value.environments).toBeUndefined();
- expect(value.statsPeriod).toEqual('14d');
- });
- it('omits defaults', function () {
- wrapper.setProps({
- location: {
- query: {
- sort: 'date',
- groupStatsPeriod: '24h',
- },
- },
- });
- const value = wrapper.instance().getEndpointParams();
- expect(value.groupStatsPeriod).toBeUndefined();
- expect(value.sort).toBeUndefined();
- });
- it('uses saved search data', function () {
- const value = wrapper.instance().getEndpointParams();
- expect(value.query).toEqual(savedSearch.query);
- expect(value.project).toEqual([parseInt(savedSearch.projectId, 10)]);
- });
- });
- describe('componentDidMount', function () {
- beforeEach(function () {
- wrapper = shallow(<IssueListOverview {...props} />);
- });
- it('fetches tags and sets state', async function () {
- const instance = wrapper.instance();
- await instance.componentDidMount();
- expect(fetchTagsRequest).toHaveBeenCalled();
- expect(instance.state.tagsLoading).toBeFalsy();
- });
- it('fetches members and sets state', async function () {
- const instance = wrapper.instance();
- await instance.componentDidMount();
- await wrapper.update();
- expect(fetchMembersRequest).toHaveBeenCalled();
- const members = instance.state.memberList;
- // Spot check the resulting structure as we munge it a bit.
- expect(members).toBeTruthy();
- expect(members[project.slug]).toBeTruthy();
- expect(members[project.slug][0].email).toBeTruthy();
- });
- it('fetches groups when there is no searchid', async function () {
- await wrapper.instance().componentDidMount();
- });
- });
- describe('componentDidUpdate fetching groups', function () {
- let fetchDataMock;
- beforeEach(function () {
- fetchDataMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/issues/',
- body: [group],
- headers: {
- Link: DEFAULT_LINKS_HEADER,
- },
- });
- fetchDataMock.mockReset();
- wrapper = shallow(<IssueListOverview {...props} />);
- });
- it('fetches data on selection change', function () {
- const selection = {projects: [99], environments: [], datetime: {period: '24h'}};
- wrapper.setProps({selection, foo: 'bar'});
- expect(fetchDataMock).toHaveBeenCalled();
- });
- it('fetches data on savedSearch change', function () {
- savedSearch = {id: '1', query: 'is:resolved'};
- wrapper.setProps({savedSearch});
- wrapper.update();
- expect(fetchDataMock).toHaveBeenCalled();
- });
- it('fetches data on location change', async function () {
- const queryAttrs = ['query', 'sort', 'statsPeriod', 'cursor', 'groupStatsPeriod'];
- const location = cloneDeep(props.location);
- for (const [i, attr] of queryAttrs.entries()) {
- // reclone each iteration so that only one property changes.
- const newLocation = cloneDeep(location);
- newLocation.query[attr] = 'newValue';
- wrapper.setProps({location: newLocation});
- await tick();
- wrapper.update();
- // Each property change after the first will actually cause two new
- // fetchData calls, one from the property change and another from a
- // change in this.state.issuesLoading going from false to true.
- expect(fetchDataMock).toHaveBeenCalledTimes(2 * i + 1);
- }
- });
- it('uses correct statsPeriod when fetching issues list and no datetime given', async function () {
- const selection = {projects: [99], environments: [], datetime: {}};
- wrapper.setProps({selection, foo: 'bar'});
- expect(fetchDataMock).toHaveBeenLastCalledWith(
- '/organizations/org-slug/issues/',
- expect.objectContaining({
- data:
- 'collapse=stats&expand=owners&limit=25&project=99&query=is%3Aunresolved&shortIdLookup=1&statsPeriod=14d',
- })
- );
- });
- });
- describe('componentDidUpdate fetching members', function () {
- beforeEach(function () {
- wrapper = shallow(<IssueListOverview {...props} />);
- wrapper.instance().fetchData = jest.fn();
- });
- it('fetches memberlist on project change', function () {
- // Called during componentDidMount
- expect(fetchMembersRequest).toHaveBeenCalledTimes(1);
- const selection = {
- projects: [99],
- environments: [],
- datetime: {period: '24h'},
- };
- wrapper.setProps({selection});
- wrapper.update();
- expect(fetchMembersRequest).toHaveBeenCalledTimes(2);
- });
- });
- describe('componentDidUpdate fetching tags', function () {
- beforeEach(function () {
- wrapper = shallow(<IssueListOverview {...props} />);
- wrapper.instance().fetchData = jest.fn();
- });
- it('fetches tags on project change', function () {
- // Called during componentDidMount
- expect(fetchTagsRequest).toHaveBeenCalledTimes(1);
- const selection = {
- projects: [99],
- environments: [],
- datetime: {period: '24h'},
- };
- wrapper.setProps({selection});
- wrapper.update();
- expect(fetchTagsRequest).toHaveBeenCalledTimes(2);
- });
- });
- describe('processingIssues', function () {
- beforeEach(function () {
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- });
- it('fetches and displays processing issues', async function () {
- const instance = wrapper.instance();
- instance.componentDidMount();
- await wrapper.update();
- GroupStore.add([group]);
- wrapper.setState({
- groupIds: ['1'],
- loading: false,
- });
- const issues = wrapper.find('ProcessingIssueList');
- expect(issues).toHaveLength(1);
- });
- });
- describe('render states', function () {
- beforeEach(function () {
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- });
- it('displays the loading icon', function () {
- wrapper.setState({savedSearchLoading: true});
- expect(wrapper.find('LoadingIndicator')).toHaveLength(1);
- });
- it('displays an error', function () {
- wrapper.setState({
- error: 'Things broke',
- savedSearchLoading: false,
- issuesLoading: false,
- });
- const error = wrapper.find('LoadingError');
- expect(error).toHaveLength(1);
- expect(error.props().message).toEqual('Things broke');
- });
- it('displays congrats robots animation with only is:unresolved query', async function () {
- wrapper.setState({
- savedSearchLoading: false,
- issuesLoading: false,
- error: false,
- groupIds: [],
- });
- await tick();
- wrapper.update();
- expect(wrapper.find('NoUnresolvedIssues').exists()).toBe(true);
- });
- it('displays an empty resultset with is:unresolved and level:error query', async function () {
- const errorsOnlyQuery = {
- ...props,
- location: {
- query: {query: 'is:unresolved level:error'},
- },
- };
- wrapper = mountWithTheme(<IssueListOverview {...errorsOnlyQuery} />);
- wrapper.setState({
- savedSearchLoading: false,
- issuesLoading: false,
- error: false,
- groupIds: [],
- fetchingSentFirstEvent: false,
- sentFirstEvent: true,
- });
- await tick();
- wrapper.update();
- expect(wrapper.find('EmptyStateWarning').exists()).toBe(true);
- });
- it('displays an empty resultset with has:browser query', async function () {
- const hasBrowserQuery = {
- ...props,
- location: {
- query: {query: 'has:browser'},
- },
- };
- wrapper = mountWithTheme(<IssueListOverview {...hasBrowserQuery} />);
- wrapper.setState({
- savedSearchLoading: false,
- issuesLoading: false,
- error: false,
- groupIds: [],
- fetchingSentFirstEvent: false,
- sentFirstEvent: true,
- });
- await tick();
- wrapper.update();
- expect(wrapper.find('EmptyStateWarning').exists()).toBe(true);
- });
- });
- describe('Error Robot', function () {
- const createWrapper = moreProps => {
- const defaultProps = {
- ...props,
- savedSearchLoading: false,
- useOrgSavedSearches: true,
- selection: {
- projects: [],
- environments: [],
- datetime: {period: '14d'},
- },
- location: {query: {query: 'is:unresolved'}, search: 'query=is:unresolved'},
- params: {orgId: organization.slug},
- organization: TestStubs.Organization({
- projects: [],
- }),
- ...moreProps,
- };
- const localWrapper = mountWithTheme(<IssueListOverview {...defaultProps} />);
- localWrapper.setState({
- error: false,
- issuesLoading: false,
- groupIds: [],
- });
- return localWrapper;
- };
- it('displays when no projects selected and all projects user is member of, does not have first event', async function () {
- const projects = [
- TestStubs.Project({
- id: '1',
- slug: 'foo',
- isMember: true,
- firstEvent: false,
- }),
- TestStubs.Project({
- id: '2',
- slug: 'bar',
- isMember: true,
- firstEvent: false,
- }),
- TestStubs.Project({
- id: '3',
- slug: 'baz',
- isMember: true,
- firstEvent: false,
- }),
- ];
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/sent-first-event/',
- query: {
- is_member: true,
- },
- body: {sentFirstEvent: false},
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: projects,
- });
- MockApiClient.addMockResponse({
- url: '/projects/org-slug/foo/issues/',
- body: [],
- });
- wrapper = createWrapper({
- organization: TestStubs.Organization({
- projects,
- }),
- });
- await tick();
- wrapper.update();
- expect(wrapper.find(ErrorRobot)).toHaveLength(1);
- });
- it('does not display when no projects selected and any projects have a first event', async function () {
- const projects = [
- TestStubs.Project({
- id: '1',
- slug: 'foo',
- isMember: true,
- firstEvent: false,
- }),
- TestStubs.Project({
- id: '2',
- slug: 'bar',
- isMember: true,
- firstEvent: true,
- }),
- TestStubs.Project({
- id: '3',
- slug: 'baz',
- isMember: true,
- firstEvent: false,
- }),
- ];
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/sent-first-event/',
- query: {
- is_member: true,
- },
- body: {sentFirstEvent: true},
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: projects,
- });
- wrapper = createWrapper({
- organization: TestStubs.Organization({
- projects,
- }),
- });
- await tick();
- wrapper.update();
- expect(wrapper.find(ErrorRobot)).toHaveLength(0);
- });
- it('displays when all selected projects do not have first event', async function () {
- const projects = [
- TestStubs.Project({
- id: '1',
- slug: 'foo',
- isMember: true,
- firstEvent: false,
- }),
- TestStubs.Project({
- id: '2',
- slug: 'bar',
- isMember: true,
- firstEvent: false,
- }),
- TestStubs.Project({
- id: '3',
- slug: 'baz',
- isMember: true,
- firstEvent: false,
- }),
- ];
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/sent-first-event/',
- query: {
- project: [1, 2],
- },
- body: {sentFirstEvent: false},
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: projects,
- });
- MockApiClient.addMockResponse({
- url: '/projects/org-slug/foo/issues/',
- body: [],
- });
- wrapper = createWrapper({
- selection: {
- projects: [1, 2],
- environments: [],
- datetime: {period: '14d'},
- },
- organization: TestStubs.Organization({
- projects,
- }),
- });
- await tick();
- wrapper.update();
- expect(wrapper.find(ErrorRobot)).toHaveLength(1);
- });
- it('does not display when any selected projects have first event', function () {
- const projects = [
- TestStubs.Project({
- id: '1',
- slug: 'foo',
- isMember: true,
- firstEvent: false,
- }),
- TestStubs.Project({
- id: '2',
- slug: 'bar',
- isMember: true,
- firstEvent: true,
- }),
- TestStubs.Project({
- id: '3',
- slug: 'baz',
- isMember: true,
- firstEvent: true,
- }),
- ];
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/sent-first-event/',
- query: {
- project: [1, 2],
- },
- body: {sentFirstEvent: true},
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: projects,
- });
- wrapper = createWrapper({
- selection: {
- projects: [1, 2],
- environments: [],
- datetime: {period: '14d'},
- },
- organization: TestStubs.Organization({
- projects,
- }),
- });
- expect(wrapper.find(ErrorRobot)).toHaveLength(0);
- });
- });
- describe('with inbox feature', function () {
- const parseLinkHeaderSpy = jest.spyOn(parseLinkHeader, 'default');
- it('renders inbox layout', function () {
- organization.features = ['inbox'];
- organization.experiments = {InboxExperiment: 1};
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- expect(wrapper.find('IssueListHeader').exists()).toBeTruthy();
- });
- it('displays a count that represents the current page', function () {
- organization.features = ['inbox'];
- parseLinkHeaderSpy.mockReturnValue({
- next: {
- results: true,
- },
- previous: {
- results: false,
- },
- });
- props = {
- ...props,
- location: {
- query: {
- cursor: 'some cursor',
- page: 0,
- },
- },
- };
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- wrapper.setState({
- groupIds: range(0, 25).map(String),
- queryCount: 500,
- queryMaxCount: 1000,
- });
- const paginationWrapper = wrapper.find('PaginationWrapper');
- expect(paginationWrapper.text()).toBe('Showing 25 of 500 issues');
- parseLinkHeaderSpy.mockReturnValue({
- next: {
- results: true,
- },
- previous: {
- results: true,
- },
- });
- wrapper.setProps({
- location: {
- query: {
- cursor: 'some cursor',
- page: 1,
- },
- },
- });
- expect(paginationWrapper.text()).toBe('Showing 50 of 500 issues');
- expect(wrapper.find('IssueListHeader').exists()).toBeTruthy();
- });
- it('displays a count that makes sense based on the current page', function () {
- organization.features = ['inbox'];
- parseLinkHeaderSpy.mockReturnValue({
- next: {
- // Is at last page according to the cursor
- results: false,
- },
- previous: {
- results: true,
- },
- });
- props = {
- ...props,
- location: {
- query: {
- cursor: 'some cursor',
- page: 3,
- },
- },
- };
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- wrapper.setState({
- groupIds: range(0, 25).map(String),
- queryCount: 500,
- queryMaxCount: 1000,
- });
- const paginationWrapper = wrapper.find('PaginationWrapper');
- expect(paginationWrapper.text()).toBe('Showing 500 of 500 issues');
- parseLinkHeaderSpy.mockReturnValue({
- next: {
- results: true,
- },
- previous: {
- // Is at first page according to cursor
- results: false,
- },
- });
- wrapper.setProps({
- location: {
- query: {
- cursor: 'some cursor',
- page: 2,
- },
- },
- });
- expect(paginationWrapper.text()).toBe('Showing 25 of 500 issues');
- expect(wrapper.find('IssueListHeader').exists()).toBeTruthy();
- });
- it('displays a count based on items removed', function () {
- organization.features = ['inbox'];
- parseLinkHeaderSpy.mockReturnValue({
- next: {
- results: true,
- },
- previous: {
- results: true,
- },
- });
- props = {
- ...props,
- location: {
- query: {
- cursor: 'some cursor',
- page: 1,
- },
- },
- };
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- wrapper.setState({
- groupIds: range(0, 25).map(String),
- queryCount: 75,
- itemsRemoved: 1,
- queryMaxCount: 1000,
- });
- const paginationWrapper = wrapper.find('PaginationWrapper');
- // 2nd page subtracts the one removed
- expect(paginationWrapper.text()).toBe('Showing 49 of 74 issues');
- });
- });
- describe('with relative change feature', function () {
- it('defaults to larger graph selection', function () {
- organization.features = ['issue-list-trend-sort'];
- props.location = {
- query: {query: 'is:unresolved', sort: 'trend'},
- search: 'query=is:unresolved',
- };
- wrapper = mountWithTheme(<IssueListOverview {...props} />);
- expect(wrapper.instance().getGroupStatsPeriod()).toBe('auto');
- });
- });
- });
|