|
4 | 4 | * you may not use this file except in compliance with the Elastic License. |
5 | 5 | */ |
6 | 6 |
|
7 | | -import { PolicyListState } from '../../types'; |
| 7 | +import { EndpointAppLocation, PolicyListState } from '../../types'; |
8 | 8 | import { applyMiddleware, createStore, Dispatch, Store } from 'redux'; |
9 | 9 | import { AppAction } from '../action'; |
10 | 10 | import { policyListReducer } from './reducer'; |
11 | 11 | import { policyListMiddlewareFactory } from './middleware'; |
12 | 12 | import { coreMock } from '../../../../../../../../src/core/public/mocks'; |
13 | | -import { CoreStart } from 'kibana/public'; |
14 | | -import { selectIsLoading } from './selectors'; |
| 13 | +import { isOnPolicyListPage, selectIsLoading, urlSearchParams } from './selectors'; |
15 | 14 | import { DepsStartMock, depsStartMock } from '../../mocks'; |
| 15 | +import { |
| 16 | + createSpyMiddleware, |
| 17 | + MiddlewareActionSpyHelper, |
| 18 | + setPolicyListApiMockImplementation, |
| 19 | +} from './test_mock_utils'; |
| 20 | +import { INGEST_API_DATASOURCES } from './services/ingest'; |
16 | 21 |
|
17 | 22 | describe('policy list store concerns', () => { |
18 | | - const sleep = () => new Promise(resolve => setTimeout(resolve, 1000)); |
19 | | - let fakeCoreStart: jest.Mocked<CoreStart>; |
| 23 | + let fakeCoreStart: ReturnType<typeof coreMock.createStart>; |
20 | 24 | let depsStart: DepsStartMock; |
21 | 25 | let store: Store<PolicyListState>; |
22 | 26 | let getState: typeof store['getState']; |
23 | 27 | let dispatch: Dispatch<AppAction>; |
| 28 | + let waitForAction: MiddlewareActionSpyHelper['waitForAction']; |
24 | 29 |
|
25 | 30 | beforeEach(() => { |
26 | 31 | fakeCoreStart = coreMock.createStart({ basePath: '/mock' }); |
27 | 32 | depsStart = depsStartMock(); |
| 33 | + setPolicyListApiMockImplementation(fakeCoreStart.http); |
| 34 | + let actionSpyMiddleware; |
| 35 | + ({ actionSpyMiddleware, waitForAction } = createSpyMiddleware<PolicyListState>()); |
| 36 | + |
28 | 37 | store = createStore( |
29 | 38 | policyListReducer, |
30 | | - applyMiddleware(policyListMiddlewareFactory(fakeCoreStart, depsStart)) |
| 39 | + applyMiddleware(policyListMiddlewareFactory(fakeCoreStart, depsStart), actionSpyMiddleware) |
31 | 40 | ); |
32 | 41 | getState = store.getState; |
33 | 42 | dispatch = store.dispatch; |
34 | 43 | }); |
35 | 44 |
|
36 | | - // https://github.com/elastic/kibana/issues/58972 |
37 | | - test.skip('it sets `isLoading` when `userNavigatedToPage`', async () => { |
38 | | - expect(selectIsLoading(getState())).toBe(false); |
39 | | - dispatch({ type: 'userNavigatedToPage', payload: 'policyListPage' }); |
40 | | - expect(selectIsLoading(getState())).toBe(true); |
41 | | - await sleep(); |
42 | | - expect(selectIsLoading(getState())).toBe(false); |
| 45 | + it('it does nothing on `userChangedUrl` if pathname is NOT `/policy`', async () => { |
| 46 | + const state = getState(); |
| 47 | + expect(isOnPolicyListPage(state)).toBe(false); |
| 48 | + dispatch({ |
| 49 | + type: 'userChangedUrl', |
| 50 | + payload: { |
| 51 | + pathname: '/foo', |
| 52 | + search: '', |
| 53 | + hash: '', |
| 54 | + } as EndpointAppLocation, |
| 55 | + }); |
| 56 | + expect(getState()).toEqual(state); |
43 | 57 | }); |
44 | 58 |
|
45 | | - // https://github.com/elastic/kibana/issues/58896 |
46 | | - test.skip('it sets `isLoading` when `userPaginatedPolicyListTable`', async () => { |
| 59 | + it('it reports `isOnPolicyListPage` correctly when router pathname is `/policy`', async () => { |
| 60 | + dispatch({ |
| 61 | + type: 'userChangedUrl', |
| 62 | + payload: { |
| 63 | + pathname: '/policy', |
| 64 | + search: '', |
| 65 | + hash: '', |
| 66 | + }, |
| 67 | + }); |
| 68 | + expect(isOnPolicyListPage(getState())).toBe(true); |
| 69 | + }); |
| 70 | + |
| 71 | + it('it sets `isLoading` when `userChangedUrl`', async () => { |
47 | 72 | expect(selectIsLoading(getState())).toBe(false); |
48 | 73 | dispatch({ |
49 | | - type: 'userPaginatedPolicyListTable', |
| 74 | + type: 'userChangedUrl', |
50 | 75 | payload: { |
51 | | - pageSize: 10, |
52 | | - pageIndex: 1, |
| 76 | + pathname: '/policy', |
| 77 | + search: '', |
| 78 | + hash: '', |
53 | 79 | }, |
54 | 80 | }); |
55 | 81 | expect(selectIsLoading(getState())).toBe(true); |
56 | | - await sleep(); |
| 82 | + await waitForAction('serverReturnedPolicyListData'); |
57 | 83 | expect(selectIsLoading(getState())).toBe(false); |
58 | 84 | }); |
59 | 85 |
|
60 | | - test('it resets state on `userNavigatedFromPage` action', async () => { |
| 86 | + it('it resets state on `userChangedUrl` and pathname is NOT `/policy`', async () => { |
| 87 | + dispatch({ |
| 88 | + type: 'userChangedUrl', |
| 89 | + payload: { |
| 90 | + pathname: '/policy', |
| 91 | + search: '', |
| 92 | + hash: '', |
| 93 | + }, |
| 94 | + }); |
| 95 | + await waitForAction('serverReturnedPolicyListData'); |
61 | 96 | dispatch({ |
62 | | - type: 'serverReturnedPolicyListData', |
| 97 | + type: 'userChangedUrl', |
63 | 98 | payload: { |
64 | | - policyItems: [], |
65 | | - pageIndex: 20, |
66 | | - pageSize: 50, |
67 | | - total: 200, |
| 99 | + pathname: '/foo', |
| 100 | + search: '', |
| 101 | + hash: '', |
68 | 102 | }, |
69 | 103 | }); |
70 | | - dispatch({ type: 'userNavigatedFromPage', payload: 'policyListPage' }); |
71 | 104 | expect(getState()).toEqual({ |
| 105 | + apiError: undefined, |
| 106 | + location: undefined, |
72 | 107 | policyItems: [], |
73 | 108 | isLoading: false, |
74 | 109 | pageIndex: 0, |
75 | 110 | pageSize: 10, |
76 | 111 | total: 0, |
77 | 112 | }); |
78 | 113 | }); |
| 114 | + it('uses default pagination params when not included in url', async () => { |
| 115 | + dispatch({ |
| 116 | + type: 'userChangedUrl', |
| 117 | + payload: { |
| 118 | + pathname: '/policy', |
| 119 | + search: '', |
| 120 | + hash: '', |
| 121 | + }, |
| 122 | + }); |
| 123 | + await waitForAction('serverReturnedPolicyListData'); |
| 124 | + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { |
| 125 | + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 10 }, |
| 126 | + }); |
| 127 | + }); |
| 128 | + |
| 129 | + describe('when url contains search params', () => { |
| 130 | + const dispatchUserChangedUrl = (searchParams: string = '') => |
| 131 | + dispatch({ |
| 132 | + type: 'userChangedUrl', |
| 133 | + payload: { |
| 134 | + pathname: '/policy', |
| 135 | + search: searchParams, |
| 136 | + hash: '', |
| 137 | + }, |
| 138 | + }); |
| 139 | + |
| 140 | + it('uses pagination params from url', async () => { |
| 141 | + dispatchUserChangedUrl('?page_size=50&page_index=0'); |
| 142 | + await waitForAction('serverReturnedPolicyListData'); |
| 143 | + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { |
| 144 | + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 50 }, |
| 145 | + }); |
| 146 | + }); |
| 147 | + it('uses defaults for params not in url', async () => { |
| 148 | + dispatchUserChangedUrl('?page_index=99'); |
| 149 | + expect(urlSearchParams(getState())).toEqual({ |
| 150 | + page_index: 99, |
| 151 | + page_size: 10, |
| 152 | + }); |
| 153 | + dispatchUserChangedUrl('?page_size=50'); |
| 154 | + expect(urlSearchParams(getState())).toEqual({ |
| 155 | + page_index: 0, |
| 156 | + page_size: 50, |
| 157 | + }); |
| 158 | + }); |
| 159 | + it('accepts only positive numbers for page_index and page_size', async () => { |
| 160 | + dispatchUserChangedUrl('?page_size=-50&page_index=-99'); |
| 161 | + await waitForAction('serverReturnedPolicyListData'); |
| 162 | + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { |
| 163 | + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 10 }, |
| 164 | + }); |
| 165 | + }); |
| 166 | + it('it ignores non-numeric values for page_index and page_size', async () => { |
| 167 | + dispatchUserChangedUrl('?page_size=fifty&page_index=ten'); |
| 168 | + await waitForAction('serverReturnedPolicyListData'); |
| 169 | + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { |
| 170 | + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 10 }, |
| 171 | + }); |
| 172 | + }); |
| 173 | + it('accepts only known values for `page_size`', async () => { |
| 174 | + dispatchUserChangedUrl('?page_size=300&page_index=10'); |
| 175 | + await waitForAction('serverReturnedPolicyListData'); |
| 176 | + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { |
| 177 | + query: { kuery: 'datasources.package.name: endpoint', page: 11, perPage: 10 }, |
| 178 | + }); |
| 179 | + }); |
| 180 | + it(`ignores unknown url search params`, async () => { |
| 181 | + dispatchUserChangedUrl('?page_size=20&page_index=10&foo=bar'); |
| 182 | + expect(urlSearchParams(getState())).toEqual({ |
| 183 | + page_index: 10, |
| 184 | + page_size: 20, |
| 185 | + }); |
| 186 | + }); |
| 187 | + it(`uses last param value if param is defined multiple times`, async () => { |
| 188 | + dispatchUserChangedUrl('?page_size=20&page_size=50&page_index=20&page_index=40'); |
| 189 | + expect(urlSearchParams(getState())).toEqual({ |
| 190 | + page_index: 20, |
| 191 | + page_size: 20, |
| 192 | + }); |
| 193 | + }); |
| 194 | + }); |
79 | 195 | }); |
0 commit comments