phobos_checkpoint_ui 0.4.0 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/frontend/.gitignore +4 -0
  4. data/frontend/src/actions/events-search.js +11 -11
  5. data/frontend/src/actions/events-search.spec.js +21 -21
  6. data/frontend/src/actions/failures/details.js +42 -0
  7. data/frontend/src/actions/failures/details.spec.js +71 -0
  8. data/frontend/src/actions/failures/overview.js +14 -0
  9. data/frontend/src/actions/failures/overview.spec.js +20 -0
  10. data/frontend/src/actions/failures/retry.js +58 -0
  11. data/frontend/src/actions/failures/retry.spec.js +117 -0
  12. data/frontend/src/actions/failures/search/index.js +76 -0
  13. data/frontend/src/actions/failures/search/index.spec.js +197 -0
  14. data/frontend/src/actions/index.js +24 -5
  15. data/frontend/src/actions/navigation/index.js +5 -0
  16. data/frontend/src/actions/navigation/index.spec.js +21 -0
  17. data/frontend/src/api.js +11 -0
  18. data/frontend/src/components/{event-overview/attribute.js → attribute/index.js} +0 -0
  19. data/frontend/src/components/empty-event/index.js +20 -0
  20. data/frontend/src/components/empty-event/index.spec.js +38 -0
  21. data/frontend/src/components/event-overview/index.js +1 -1
  22. data/frontend/src/components/event-retry-dialog/index.js +1 -1
  23. data/frontend/src/components/failure/error-message.js +19 -0
  24. data/frontend/src/components/failure/error-message.scss +8 -0
  25. data/frontend/src/components/failure/event.scss +3 -0
  26. data/frontend/src/components/failure/index.js +82 -0
  27. data/frontend/src/components/failure/index.spec.js +89 -0
  28. data/frontend/src/components/failure/loading.js +16 -0
  29. data/frontend/src/components/failure/overview/failure-overview.scss +28 -0
  30. data/frontend/src/components/failure/overview/index.js +60 -0
  31. data/frontend/src/components/failure/overview/index.spec.js +71 -0
  32. data/frontend/src/components/failure/overview-dialog/event-overview-dialog.scss +15 -0
  33. data/frontend/src/components/failure/overview-dialog/index.js +90 -0
  34. data/frontend/src/components/failure/retry-dialog/index.js +72 -0
  35. data/frontend/src/components/failure/style.js +16 -0
  36. data/frontend/src/components/failures-list/failures-list.scss +49 -0
  37. data/frontend/src/components/failures-list/index.js +62 -0
  38. data/frontend/src/components/failures-list/index.spec.js +59 -0
  39. data/frontend/src/components/header/index.js +36 -2
  40. data/frontend/src/components/load-more/index.js +22 -0
  41. data/frontend/src/components/load-more/index.spec.js +54 -0
  42. data/frontend/src/components/search-input/index.js +2 -5
  43. data/frontend/src/components/search-input/index.spec.js +6 -6
  44. data/frontend/src/reducers/events.js +2 -2
  45. data/frontend/src/reducers/events.spec.js +4 -4
  46. data/frontend/src/reducers/failures/details/index.js +32 -0
  47. data/frontend/src/reducers/failures/details/index.spec.js +54 -0
  48. data/frontend/src/reducers/failures/index.js +48 -0
  49. data/frontend/src/reducers/failures/index.spec.js +95 -0
  50. data/frontend/src/reducers/index.js +4 -1
  51. data/frontend/src/reducers/index.spec.js +2 -0
  52. data/frontend/src/reducers/xhr-status.js +25 -10
  53. data/frontend/src/reducers/xhr-status.spec.js +65 -15
  54. data/frontend/src/routes.js +6 -2
  55. data/frontend/src/store.js +7 -3
  56. data/frontend/src/views/{event-details.js → events/details/index.js} +0 -0
  57. data/frontend/src/views/{events-search.js → events/search/index.js} +37 -44
  58. data/frontend/src/views/{events-search.scss → events/search/index.scss} +0 -0
  59. data/frontend/src/views/{events-search.spec.js → events/search/index.spec.js} +35 -25
  60. data/frontend/src/views/failures/details/index.js +50 -0
  61. data/frontend/src/views/failures/search/index.js +113 -0
  62. data/frontend/src/views/failures/search/index.scss +24 -0
  63. data/frontend/src/views/failures/search/index.spec.js +106 -0
  64. data/lib/phobos_checkpoint_ui/version.rb +1 -1
  65. data/phobos_checkpoint_ui.gemspec +1 -1
  66. metadata +53 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 76b2e76b2861ed3abde048b5efeb27bc7bb134d8
4
- data.tar.gz: 2660845c932a00a035ffb4e53ac1e86c0ea45534
3
+ metadata.gz: c06ac3b49f17bb1a0cfd0b99c381cbf472ea99c2
4
+ data.tar.gz: 6a20e89e24e36288a4448c6e05d560613c7440b6
5
5
  SHA512:
6
- metadata.gz: f16f45cb5b6c95c99b56852fd7c99595c0ccc683b82af1d0ac7009c0bfa2b4d8787c7d010f9ca8c9f587c6e54f60dd2d629fcf1bf5e678af942aa48a81ef042d
7
- data.tar.gz: 0acd74e372d733671487de76a87dfd00d3245981348aeacf37f2417acfdb75075667b2002117d7bac37468060725da6bad34aa3c1bb541ea9c247c5b34550d0a
6
+ metadata.gz: 9c9ff42eee60f0ec01a4ce14b24f3f9903444a91a41a6bd140aae7eef2d427817275f2300ed768fa8b08bc2c5a04a4a9270681697d4116c991a3f86b04f1085a
7
+ data.tar.gz: 11524361e949b14a83a0404c6161581d08b0342b8628ea162e4a7432c660f32337077cb0c56e4e6e670c9b2aed9592bb7246bf4348c36aa7228a3b5c2e73a55f
data/CHANGELOG.md CHANGED
@@ -4,13 +4,17 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## 1.0.0.rc1 (2017-03-01)
8
+
9
+ - [feature] Add GUI interacting with PhobosDBCheckpoint failures
10
+
7
11
  ## 0.4.0 (2017-01-28)
8
12
 
9
13
  - [enhancement] Add /ping endpoint
10
14
 
11
15
  ## 0.3.0 (2017-01-28)
12
16
 
13
- - [bugfix] Gem should require phobos db checkpoint and its events api
17
+ - [bugfix] Gem should require PhobosDBCheckpoint
14
18
 
15
19
  ## 0.2.0 (2016-10-10)
16
20
 
@@ -0,0 +1,4 @@
1
+ coverage
2
+ node_modules
3
+ npm-debug.log
4
+ dist
@@ -3,34 +3,34 @@ import { addFlashMessage } from 'actions/flash-messages'
3
3
  import { history } from 'routes'
4
4
 
5
5
  import {
6
- TRIGGER_SEARCH,
7
- REQUEST_SEARCH_RESULTS,
8
- RECEIVE_SEARCH_RESULTS,
9
- REQUEST_SEARCH_RESULTS_FAILED,
10
- LOAD_MORE_SEARCH_RESULTS
6
+ TRIGGER_EVENTS_SEARCH,
7
+ REQUEST_EVENTS_SEARCH_RESULTS,
8
+ RECEIVE_EVENTS_SEARCH_RESULTS,
9
+ REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
10
+ LOAD_MORE_EVENTS_SEARCH_RESULTS
11
11
  } from 'actions'
12
12
 
13
13
  export const triggerSearch = () => (dispatch, getState) => {
14
14
  const filters = getState().eventsFilters
15
15
  return Promise
16
16
  .resolve()
17
- .then(() => history.push({ query: filters.value ? filters : {} }))
18
- .then(() => dispatch({ type: TRIGGER_SEARCH }))
17
+ .then(() => history.push({ pathname: window.location.pathname, query: filters.value ? filters : {} }))
18
+ .then(() => dispatch({ type: TRIGGER_EVENTS_SEARCH }))
19
19
  .then(() => dispatch(fetchSearchResults()))
20
20
  }
21
21
 
22
22
  const requestSearchResults = () => ({
23
- type: REQUEST_SEARCH_RESULTS
23
+ type: REQUEST_EVENTS_SEARCH_RESULTS
24
24
  })
25
25
 
26
26
  const receiveSearchResults = (data, offset) => ({
27
- type: RECEIVE_SEARCH_RESULTS,
27
+ type: RECEIVE_EVENTS_SEARCH_RESULTS,
28
28
  events: data,
29
29
  offset
30
30
  })
31
31
 
32
32
  const requestSearchResultsFailed = (query, error) => ({
33
- type: REQUEST_SEARCH_RESULTS_FAILED,
33
+ type: REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
34
34
  query,
35
35
  error
36
36
  })
@@ -68,7 +68,7 @@ export const loadMoreSearchResults = () => (dispatch, getState) => {
68
68
  return Promise
69
69
  .resolve()
70
70
  .then(() => dispatch({
71
- type: LOAD_MORE_SEARCH_RESULTS,
71
+ type: LOAD_MORE_EVENTS_SEARCH_RESULTS,
72
72
  offset: currentOffset + EVENTS_SEARCH_LIMIT
73
73
  }))
74
74
  .then(() => dispatch(fetchSearchResults()))
@@ -9,12 +9,12 @@ const middlewares = [ thunk ]
9
9
  const mockStore = configureMockStore(middlewares)
10
10
 
11
11
  import {
12
- TRIGGER_SEARCH,
13
- REQUEST_SEARCH_RESULTS,
14
- RECEIVE_SEARCH_RESULTS,
15
- REQUEST_SEARCH_RESULTS_FAILED,
12
+ TRIGGER_EVENTS_SEARCH,
13
+ REQUEST_EVENTS_SEARCH_RESULTS,
14
+ RECEIVE_EVENTS_SEARCH_RESULTS,
15
+ REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
16
16
  ADD_FLASH_MESSAGE,
17
- LOAD_MORE_SEARCH_RESULTS
17
+ LOAD_MORE_EVENTS_SEARCH_RESULTS
18
18
  } from 'actions'
19
19
 
20
20
  import {
@@ -44,8 +44,8 @@ describe('actions/event-search', () => {
44
44
  it('creates REQUEST and RECEIVE actions', (done) => {
45
45
  store.dispatch(fetchSearchResults(event)).then(() => {
46
46
  const actions = store.getActions()
47
- expect(actions[0]).toEqual({ type: REQUEST_SEARCH_RESULTS })
48
- expect(actions[1]).toEqual({ type: RECEIVE_SEARCH_RESULTS, events: [event], offset: 0 })
47
+ expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
48
+ expect(actions[1]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 0 })
49
49
  done()
50
50
  })
51
51
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
@@ -70,8 +70,8 @@ describe('actions/event-search', () => {
70
70
  it('creates REQUEST and RECEIVE actions using the filters', (done) => {
71
71
  store.dispatch(fetchSearchResults(event)).then(() => {
72
72
  const actions = store.getActions()
73
- expect(actions[0]).toEqual({ type: REQUEST_SEARCH_RESULTS })
74
- expect(actions[1]).toEqual({ type: RECEIVE_SEARCH_RESULTS, events: [event], offset: 0 })
73
+ expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
74
+ expect(actions[1]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 0 })
75
75
  done()
76
76
  })
77
77
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
@@ -96,8 +96,8 @@ describe('actions/event-search', () => {
96
96
  it('creates REQUEST and RECEIVE actions pointing to the correct offset', (done) => {
97
97
  store.dispatch(fetchSearchResults(event)).then(() => {
98
98
  const actions = store.getActions()
99
- expect(actions[0]).toEqual({ type: REQUEST_SEARCH_RESULTS })
100
- expect(actions[1]).toEqual({ type: RECEIVE_SEARCH_RESULTS, events: [event], offset: 4 })
99
+ expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
100
+ expect(actions[1]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 4 })
101
101
  done()
102
102
  })
103
103
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
@@ -125,9 +125,9 @@ describe('actions/event-search', () => {
125
125
  it('creates REQUEST and RECEIVE actions pointing to the correct offset', (done) => {
126
126
  store.dispatch(fetchSearchResults(event)).then(() => {
127
127
  const actions = store.getActions()
128
- expect(actions[0]).toEqual({ type: REQUEST_SEARCH_RESULTS })
128
+ expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
129
129
  expect(actions[1]).toEqual({
130
- type: REQUEST_SEARCH_RESULTS_FAILED,
130
+ type: REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
131
131
  query: { offset: 0 }, error: 'some error'
132
132
  })
133
133
  expect(actions[2]).toEqual({
@@ -156,12 +156,12 @@ describe('actions/event-search', () => {
156
156
  .response([event])
157
157
  })
158
158
 
159
- it('creates TRIGGER_SEARCH and REQUEST actions', (done) => {
159
+ it('creates TRIGGER_EVENTS_SEARCH and REQUEST actions', (done) => {
160
160
  store.dispatch(triggerSearch()).then(() => {
161
161
  const actions = store.getActions()
162
- expect(actions[0]).toEqual({ type: TRIGGER_SEARCH })
163
- expect(actions[1]).toEqual({ type: REQUEST_SEARCH_RESULTS })
164
- expect(actions[2]).toEqual({ type: RECEIVE_SEARCH_RESULTS, events: [event], offset: 0 })
162
+ expect(actions[0]).toEqual({ type: TRIGGER_EVENTS_SEARCH })
163
+ expect(actions[1]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
164
+ expect(actions[2]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 0 })
165
165
  done()
166
166
  })
167
167
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
@@ -183,12 +183,12 @@ describe('actions/event-search', () => {
183
183
  .response([event])
184
184
  })
185
185
 
186
- it('creates LOAD_MORE_SEARCH_RESULTS and REQUEST actions', (done) => {
186
+ it('creates LOAD_MORE_EVENTS_SEARCH_RESULTS and REQUEST actions', (done) => {
187
187
  store.dispatch(loadMoreSearchResults()).then(() => {
188
188
  const actions = store.getActions()
189
- expect(actions[0]).toEqual({ type: LOAD_MORE_SEARCH_RESULTS, offset: 4 + EVENTS_SEARCH_LIMIT })
190
- expect(actions[1]).toEqual({ type: REQUEST_SEARCH_RESULTS })
191
- expect(actions[2]).toEqual({ type: RECEIVE_SEARCH_RESULTS, events: [event], offset: 4 })
189
+ expect(actions[0]).toEqual({ type: LOAD_MORE_EVENTS_SEARCH_RESULTS, offset: 4 + EVENTS_SEARCH_LIMIT })
190
+ expect(actions[1]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
191
+ expect(actions[2]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 4 })
192
192
  done()
193
193
  })
194
194
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
@@ -0,0 +1,42 @@
1
+ import API, { parseResponseError } from 'api'
2
+ import { addFlashMessage } from 'actions/flash-messages'
3
+
4
+ import {
5
+ REQUEST_FAILURE_DETAILS,
6
+ RECEIVE_FAILURE_DETAILS,
7
+ REQUEST_FAILURE_DETAILS_FAILED
8
+ } from 'actions'
9
+
10
+ const requestFailureDetails = (failure) => ({
11
+ type: REQUEST_FAILURE_DETAILS,
12
+ failure
13
+ })
14
+
15
+ const receiveFailureDetails = (failure) => ({
16
+ type: RECEIVE_FAILURE_DETAILS,
17
+ failure
18
+ })
19
+
20
+ const requestFailureDetailsFailed = (failure, error) => ({
21
+ type: REQUEST_FAILURE_DETAILS_FAILED,
22
+ failure,
23
+ error
24
+ })
25
+
26
+ export const fetchFailureDetails = (failure) => (dispatch, getState) => {
27
+ dispatch(requestFailureDetails(failure))
28
+
29
+ return API.Failure
30
+ .findById({ id: failure.id })
31
+ .then((response) => dispatch(receiveFailureDetails(response.data)))
32
+ .catch((response) => {
33
+ const error = parseResponseError(response)
34
+ return Promise
35
+ .resolve()
36
+ .then(() => dispatch(requestFailureDetailsFailed(failure, error.message)))
37
+ .then(() => dispatch(addFlashMessage({
38
+ type: 'error',
39
+ text: error.message
40
+ })))
41
+ })
42
+ }
@@ -0,0 +1,71 @@
1
+ import 'babel-polyfill'
2
+ import Mappersmith from 'mappersmith'
3
+ import 'mappersmith/fixtures'
4
+ import configureMockStore from 'redux-mock-store'
5
+ import thunk from 'redux-thunk'
6
+
7
+ const middlewares = [ thunk ]
8
+ const mockStore = configureMockStore(middlewares)
9
+
10
+ import {
11
+ REQUEST_FAILURE_DETAILS,
12
+ RECEIVE_FAILURE_DETAILS,
13
+ REQUEST_FAILURE_DETAILS_FAILED
14
+ } from 'actions'
15
+
16
+ import { fetchFailureDetails } from 'actions/failures/details'
17
+
18
+ beforeEach(() => {
19
+ Mappersmith.Env.Fixture.clear()
20
+ })
21
+
22
+ describe('actions/failure-details', () => {
23
+ describe('#fetchFailureDetails', () => {
24
+ describe('when it succeeds', () => {
25
+ let failure, store
26
+ beforeEach(() => {
27
+ failure = { id: 1 }
28
+ store = mockStore({})
29
+ Mappersmith.Env.Fixture
30
+ .define('get')
31
+ .matching({ url: `/api/v1/failures/${failure.id}` })
32
+ .response(failure)
33
+ })
34
+
35
+ it('creates REQUEST and RECEIVE actions', (done) => {
36
+ store.dispatch(fetchFailureDetails(failure)).then(() => {
37
+ const actions = store.getActions()
38
+ expect(actions[0]).toEqual({ type: REQUEST_FAILURE_DETAILS, failure })
39
+ expect(actions[1]).toEqual({ type: RECEIVE_FAILURE_DETAILS, failure })
40
+ done()
41
+ })
42
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
43
+ })
44
+ })
45
+
46
+ describe('when it fails', () => {
47
+ it('creates REQUEST and REQUEST_FAILED actions', (done) => {
48
+ const failure = { id: 1 }
49
+ const store = mockStore({})
50
+ Mappersmith.Env.Fixture
51
+ .define('get')
52
+ .matching({ url: `/api/v1/failures/${failure.id}` })
53
+ .failure()
54
+ .response({
55
+ responseText: JSON.stringify({
56
+ error: true,
57
+ message: 'some error'
58
+ })
59
+ })
60
+
61
+ store.dispatch(fetchFailureDetails(failure)).then(() => {
62
+ const actions = store.getActions()
63
+ expect(actions[0]).toEqual({ type: REQUEST_FAILURE_DETAILS, failure })
64
+ expect(actions[1]).toEqual({ type: REQUEST_FAILURE_DETAILS_FAILED, failure, error: 'some error' })
65
+ done()
66
+ })
67
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
68
+ })
69
+ })
70
+ })
71
+ })
@@ -0,0 +1,14 @@
1
+ import {
2
+ FAILURE_SHOW_OVERVIEW,
3
+ FAILURE_HIDE_OVERVIEW
4
+ } from 'actions'
5
+
6
+ export const showFailureOverview = (failure) => ({
7
+ type: FAILURE_SHOW_OVERVIEW,
8
+ failure
9
+ })
10
+
11
+ export const hideFailureOverview = (failure) => ({
12
+ type: FAILURE_HIDE_OVERVIEW,
13
+ failure
14
+ })
@@ -0,0 +1,20 @@
1
+ import { FAILURE_SHOW_OVERVIEW, FAILURE_HIDE_OVERVIEW } from 'actions'
2
+ import { showFailureOverview, hideFailureOverview } from 'actions/failures/overview'
3
+
4
+ describe('actions/failures/overview', () => {
5
+ describe('#showFailureOverview', () => {
6
+ it('creates an action to show failure overview', () => {
7
+ const failure = { id: 1 }
8
+ const expectedAction = { type: FAILURE_SHOW_OVERVIEW, failure: failure }
9
+ expect(showFailureOverview(failure)).toEqual(expectedAction)
10
+ })
11
+ })
12
+
13
+ describe('#hideFailureOverview', () => {
14
+ it('creates an action to hide failure overview', () => {
15
+ const failure = { id: 1 }
16
+ const expectedAction = { type: FAILURE_HIDE_OVERVIEW, failure: failure }
17
+ expect(hideFailureOverview(failure)).toEqual(expectedAction)
18
+ })
19
+ })
20
+ })
@@ -0,0 +1,58 @@
1
+ import API, { parseResponseError } from 'api'
2
+ import { addFlashMessage } from 'actions/flash-messages'
3
+
4
+ import {
5
+ FAILURE_SHOW_RETRY,
6
+ FAILURE_HIDE_RETRY,
7
+ REQUEST_FAILURE_RETRY,
8
+ RECEIVE_FAILURE_RETRY,
9
+ REQUEST_FAILURE_RETRY_FAILED
10
+ } from 'actions'
11
+
12
+ export const showFailureRetry = (failure) => ({
13
+ type: FAILURE_SHOW_RETRY,
14
+ failure
15
+ })
16
+
17
+ export const hideFailureRetry = (failure) => ({
18
+ type: FAILURE_HIDE_RETRY,
19
+ failure
20
+ })
21
+
22
+ const requestFailureRetry = (failure) => ({
23
+ type: REQUEST_FAILURE_RETRY,
24
+ failure: failure
25
+ })
26
+
27
+ const receiveFailureRetry = (failure, data) => ({
28
+ type: RECEIVE_FAILURE_RETRY,
29
+ failure: failure,
30
+ acknowledged: data.acknowledged
31
+ })
32
+
33
+ const requestFailureRetryFailed = (failure, error) => ({
34
+ type: REQUEST_FAILURE_RETRY_FAILED,
35
+ failure: failure,
36
+ error
37
+ })
38
+
39
+ export const performFailureRetry = (failure) => (dispatch, getState) => {
40
+ dispatch(requestFailureRetry(failure))
41
+ return API.Failure
42
+ .retry({id: failure.id})
43
+ .then((response) => {
44
+ return Promise
45
+ .resolve()
46
+ .then(() => dispatch(receiveFailureRetry(failure, response.data)))
47
+ .then(() => dispatch(hideFailureRetry(failure)))
48
+ .then(() => dispatch(addFlashMessage({
49
+ type: 'success',
50
+ text: `Failure retried with success. Acknowledged: ${response.data.acknowledged}`,
51
+ autoClose: true
52
+ })))
53
+ })
54
+ .catch((response) => {
55
+ const error = parseResponseError(response)
56
+ dispatch(requestFailureRetryFailed(failure, error.message))
57
+ })
58
+ }
@@ -0,0 +1,117 @@
1
+ import 'babel-polyfill'
2
+ import Mappersmith from 'mappersmith'
3
+ import 'mappersmith/fixtures'
4
+ import configureMockStore from 'redux-mock-store'
5
+ import thunk from 'redux-thunk'
6
+
7
+ const middlewares = [ thunk ]
8
+ const mockStore = configureMockStore(middlewares)
9
+
10
+ import {
11
+ FAILURE_SHOW_RETRY,
12
+ FAILURE_HIDE_RETRY,
13
+ REQUEST_FAILURE_RETRY,
14
+ RECEIVE_FAILURE_RETRY,
15
+ ADD_FLASH_MESSAGE,
16
+ REQUEST_FAILURE_RETRY_FAILED
17
+ } from 'actions'
18
+
19
+ import {
20
+ showFailureRetry,
21
+ hideFailureRetry,
22
+ performFailureRetry
23
+ } from 'actions/failures/retry'
24
+
25
+ beforeEach(() => {
26
+ Mappersmith.Env.Fixture.clear()
27
+ })
28
+
29
+ describe('actions/failures/retry', () => {
30
+ describe('#showFailureRetry', () => {
31
+ it('creates an action to show failure retry', () => {
32
+ const failure = { id: 1 }
33
+ const expectedAction = { type: FAILURE_SHOW_RETRY, failure }
34
+ expect(showFailureRetry(failure)).toEqual(expectedAction)
35
+ })
36
+ })
37
+
38
+ describe('#hideFailureRetry', () => {
39
+ it('creates an action to hide failure retry', () => {
40
+ const failure = { id: 1 }
41
+ const expectedAction = { type: FAILURE_HIDE_RETRY, failure }
42
+ expect(hideFailureRetry(failure)).toEqual(expectedAction)
43
+ })
44
+ })
45
+
46
+ describe('#performFailureRetry', () => {
47
+ describe('when it succeeds', () => {
48
+ let failure, store
49
+ beforeEach(() => {
50
+ failure = { id: 1 }
51
+ store = mockStore({})
52
+ Mappersmith.Env.Fixture
53
+ .define('post')
54
+ .matching({ url: `/api/v1/failures/${failure.id}/retry` })
55
+ .response({ acknowledged: true })
56
+ })
57
+
58
+ it('creates REQUEST and RECEIVE actions', (done) => {
59
+ store.dispatch(performFailureRetry(failure)).then(() => {
60
+ const actions = store.getActions()
61
+ expect(actions[0]).toEqual({ type: REQUEST_FAILURE_RETRY, failure })
62
+ expect(actions[1]).toEqual({ type: RECEIVE_FAILURE_RETRY, failure, acknowledged: true })
63
+ done()
64
+ })
65
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
66
+ })
67
+
68
+ it('creates an action to hide the failure retry', (done) => {
69
+ store.dispatch(performFailureRetry(failure)).then(() => {
70
+ const actions = store.getActions()
71
+ expect(actions[2]).toEqual({ type: FAILURE_HIDE_RETRY, failure })
72
+ done()
73
+ })
74
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
75
+ })
76
+
77
+ it('create an action to add a success flash message', (done) => {
78
+ store.dispatch(performFailureRetry(failure)).then(() => {
79
+ const actions = store.getActions()
80
+ expect(actions[3]).toEqual({ type: ADD_FLASH_MESSAGE, message: {
81
+ id: jasmine.any(String),
82
+ type: 'success',
83
+ text: 'Failure retried with success. Acknowledged: true',
84
+ autoClose: true
85
+ }})
86
+ done()
87
+ })
88
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
89
+ })
90
+ })
91
+
92
+ describe('when it fails', () => {
93
+ it('creates REQUEST and REQUEST_FAILED actions', (done) => {
94
+ const failure = { id: 1 }
95
+ const store = mockStore({})
96
+ Mappersmith.Env.Fixture
97
+ .define('post')
98
+ .matching({ url: `/api/v1/failures/${failure.id}/retry` })
99
+ .failure()
100
+ .response({
101
+ responseText: JSON.stringify({
102
+ error: true,
103
+ message: 'some error'
104
+ })
105
+ })
106
+
107
+ store.dispatch(performFailureRetry(failure)).then(() => {
108
+ const actions = store.getActions()
109
+ expect(actions[0]).toEqual({ type: REQUEST_FAILURE_RETRY, failure })
110
+ expect(actions[1]).toEqual({ type: REQUEST_FAILURE_RETRY_FAILED, failure, error: 'some error' })
111
+ done()
112
+ })
113
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
114
+ })
115
+ })
116
+ })
117
+ })
@@ -0,0 +1,76 @@
1
+
2
+ import API, { EVENTS_SEARCH_LIMIT, parseResponseError } from 'api'
3
+ import { addFlashMessage } from 'actions/flash-messages'
4
+ import { history } from 'routes'
5
+
6
+ import {
7
+ TRIGGER_FAILURES_SEARCH,
8
+ REQUEST_FAILURES_SEARCH_RESULTS,
9
+ RECEIVE_FAILURES_SEARCH_RESULTS,
10
+ REQUEST_FAILURES_SEARCH_RESULTS_FAILED,
11
+ LOAD_MORE_FAILURES_SEARCH_RESULTS
12
+ } from 'actions'
13
+
14
+ export const triggerSearch = () => (dispatch, getState) => {
15
+ const filters = getState().eventsFilters
16
+ return Promise
17
+ .resolve()
18
+ .then(() => history.push({ pathname: window.location.pathname, query: filters.value ? filters : {} }))
19
+ .then(() => dispatch({ type: TRIGGER_FAILURES_SEARCH }))
20
+ .then(() => dispatch(fetchSearchResults()))
21
+ }
22
+
23
+ const requestSearchResults = () => ({
24
+ type: REQUEST_FAILURES_SEARCH_RESULTS
25
+ })
26
+
27
+ const receiveSearchResults = (data, offset) => ({
28
+ type: RECEIVE_FAILURES_SEARCH_RESULTS,
29
+ failures: data,
30
+ offset
31
+ })
32
+
33
+ const requestSearchResultsFailed = (query, error) => ({
34
+ type: REQUEST_FAILURES_SEARCH_RESULTS_FAILED,
35
+ query,
36
+ error
37
+ })
38
+
39
+ export const fetchSearchResults = () => (dispatch, getState) => {
40
+ dispatch(requestSearchResults())
41
+
42
+ const filter = getState().eventsFilters
43
+ const currentOffset = getState().xhrStatus.currentEventsOffset
44
+ const query = filter.value
45
+ ? {[filter.type]: filter.value}
46
+ : {}
47
+
48
+ Object.assign(query, { offset: currentOffset })
49
+
50
+ return API.Failure
51
+ .search(query)
52
+ .then((response) => {
53
+ dispatch(receiveSearchResults(response.data, currentOffset))
54
+ })
55
+ .catch((response) => {
56
+ const error = parseResponseError(response)
57
+ return Promise
58
+ .resolve()
59
+ .then(() => dispatch(requestSearchResultsFailed(query, error.message)))
60
+ .then(() => dispatch(addFlashMessage({
61
+ type: 'error',
62
+ text: `Failures search failed. "${error.message}"`
63
+ })))
64
+ })
65
+ }
66
+
67
+ export const loadMoreSearchResults = () => (dispatch, getState) => {
68
+ const currentOffset = getState().xhrStatus.currentEventsOffset
69
+ return Promise
70
+ .resolve()
71
+ .then(() => dispatch({
72
+ type: LOAD_MORE_FAILURES_SEARCH_RESULTS,
73
+ offset: currentOffset + EVENTS_SEARCH_LIMIT
74
+ }))
75
+ .then(() => dispatch(fetchSearchResults()))
76
+ }