phobos_checkpoint_ui 0.4.0 → 1.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/frontend/.gitignore +4 -0
- data/frontend/src/actions/events-search.js +11 -11
- data/frontend/src/actions/events-search.spec.js +21 -21
- data/frontend/src/actions/failures/details.js +42 -0
- data/frontend/src/actions/failures/details.spec.js +71 -0
- data/frontend/src/actions/failures/overview.js +14 -0
- data/frontend/src/actions/failures/overview.spec.js +20 -0
- data/frontend/src/actions/failures/retry.js +58 -0
- data/frontend/src/actions/failures/retry.spec.js +117 -0
- data/frontend/src/actions/failures/search/index.js +76 -0
- data/frontend/src/actions/failures/search/index.spec.js +197 -0
- data/frontend/src/actions/index.js +24 -5
- data/frontend/src/actions/navigation/index.js +5 -0
- data/frontend/src/actions/navigation/index.spec.js +21 -0
- data/frontend/src/api.js +11 -0
- data/frontend/src/components/{event-overview/attribute.js → attribute/index.js} +0 -0
- data/frontend/src/components/empty-event/index.js +20 -0
- data/frontend/src/components/empty-event/index.spec.js +38 -0
- data/frontend/src/components/event-overview/index.js +1 -1
- data/frontend/src/components/event-retry-dialog/index.js +1 -1
- data/frontend/src/components/failure/error-message.js +19 -0
- data/frontend/src/components/failure/error-message.scss +8 -0
- data/frontend/src/components/failure/event.scss +3 -0
- data/frontend/src/components/failure/index.js +82 -0
- data/frontend/src/components/failure/index.spec.js +89 -0
- data/frontend/src/components/failure/loading.js +16 -0
- data/frontend/src/components/failure/overview/failure-overview.scss +28 -0
- data/frontend/src/components/failure/overview/index.js +60 -0
- data/frontend/src/components/failure/overview/index.spec.js +71 -0
- data/frontend/src/components/failure/overview-dialog/event-overview-dialog.scss +15 -0
- data/frontend/src/components/failure/overview-dialog/index.js +90 -0
- data/frontend/src/components/failure/retry-dialog/index.js +72 -0
- data/frontend/src/components/failure/style.js +16 -0
- data/frontend/src/components/failures-list/failures-list.scss +49 -0
- data/frontend/src/components/failures-list/index.js +62 -0
- data/frontend/src/components/failures-list/index.spec.js +59 -0
- data/frontend/src/components/header/index.js +36 -2
- data/frontend/src/components/load-more/index.js +22 -0
- data/frontend/src/components/load-more/index.spec.js +54 -0
- data/frontend/src/components/search-input/index.js +2 -5
- data/frontend/src/components/search-input/index.spec.js +6 -6
- data/frontend/src/reducers/events.js +2 -2
- data/frontend/src/reducers/events.spec.js +4 -4
- data/frontend/src/reducers/failures/details/index.js +32 -0
- data/frontend/src/reducers/failures/details/index.spec.js +54 -0
- data/frontend/src/reducers/failures/index.js +48 -0
- data/frontend/src/reducers/failures/index.spec.js +95 -0
- data/frontend/src/reducers/index.js +4 -1
- data/frontend/src/reducers/index.spec.js +2 -0
- data/frontend/src/reducers/xhr-status.js +25 -10
- data/frontend/src/reducers/xhr-status.spec.js +65 -15
- data/frontend/src/routes.js +6 -2
- data/frontend/src/store.js +7 -3
- data/frontend/src/views/{event-details.js → events/details/index.js} +0 -0
- data/frontend/src/views/{events-search.js → events/search/index.js} +37 -44
- data/frontend/src/views/{events-search.scss → events/search/index.scss} +0 -0
- data/frontend/src/views/{events-search.spec.js → events/search/index.spec.js} +35 -25
- data/frontend/src/views/failures/details/index.js +50 -0
- data/frontend/src/views/failures/search/index.js +113 -0
- data/frontend/src/views/failures/search/index.scss +24 -0
- data/frontend/src/views/failures/search/index.spec.js +106 -0
- data/lib/phobos_checkpoint_ui/version.rb +1 -1
- data/phobos_checkpoint_ui.gemspec +1 -1
- metadata +53 -14
@@ -1,13 +1,13 @@
|
|
1
1
|
import React, { Component, PropTypes } from 'react'
|
2
2
|
import { connect } from 'react-redux'
|
3
|
-
import { EVENTS_SEARCH_LIMIT } from 'api'
|
4
3
|
|
4
|
+
import LoadMore from 'components/load-more'
|
5
|
+
import EmptyEvent from 'components/empty-event'
|
5
6
|
import EventsList from 'components/events-list'
|
6
7
|
import SearchInput from 'components/search-input'
|
7
8
|
import CircularProgress from 'material-ui/CircularProgress'
|
8
|
-
import RaisedButton from 'material-ui/RaisedButton'
|
9
9
|
|
10
|
-
import { fetchSearchResults, loadMoreSearchResults } from 'actions/events-search'
|
10
|
+
import { fetchSearchResults, loadMoreSearchResults, triggerSearch } from 'actions/events-search'
|
11
11
|
import { changeSearchInputFilterType, changeSearchInputFilterValue } from 'actions/search-input-filter'
|
12
12
|
import { showEventOverview } from 'actions/event-overview'
|
13
13
|
|
@@ -16,9 +16,39 @@ export class EventsSearch extends Component {
|
|
16
16
|
return {
|
17
17
|
fetchSearchResults: PropTypes.func.isRequired,
|
18
18
|
loadMoreSearchResults: PropTypes.func.isRequired,
|
19
|
+
triggerSearch: PropTypes.func.isRequired,
|
19
20
|
changeSearchInputFilterType: PropTypes.func.isRequired,
|
20
21
|
changeSearchInputFilterValue: PropTypes.func.isRequired,
|
21
|
-
showEventOverview: PropTypes.func.isRequired
|
22
|
+
showEventOverview: PropTypes.func.isRequired,
|
23
|
+
|
24
|
+
xhrStatus: PropTypes.shape({
|
25
|
+
type: PropTypes.string,
|
26
|
+
value: PropTypes.string,
|
27
|
+
isFetchingEvents: PropTypes.bool
|
28
|
+
}),
|
29
|
+
eventsFilters: PropTypes.shape({
|
30
|
+
type: PropTypes.string,
|
31
|
+
value: PropTypes.string
|
32
|
+
}),
|
33
|
+
events: PropTypes.arrayOf(
|
34
|
+
PropTypes.shape({
|
35
|
+
onShowOverview: PropTypes.func,
|
36
|
+
event: PropTypes.shape({
|
37
|
+
id: PropTypes.number,
|
38
|
+
group_id: PropTypes.string,
|
39
|
+
topic: PropTypes.string,
|
40
|
+
entity_id: PropTypes.string,
|
41
|
+
event_type: PropTypes.string,
|
42
|
+
event_time: PropTypes.string,
|
43
|
+
event_version: PropTypes.string,
|
44
|
+
checksum: PropTypes.string,
|
45
|
+
payload: PropTypes.object
|
46
|
+
})
|
47
|
+
})
|
48
|
+
),
|
49
|
+
location: PropTypes.shape({
|
50
|
+
query: PropTypes.object
|
51
|
+
})
|
22
52
|
}
|
23
53
|
}
|
24
54
|
|
@@ -39,7 +69,7 @@ export class EventsSearch extends Component {
|
|
39
69
|
|
40
70
|
return (
|
41
71
|
<div className='events-search'>
|
42
|
-
<SearchInput filterType={type} filterValue={value}/>
|
72
|
+
<SearchInput triggerSearch={this.props.triggerSearch} filterType={type} filterValue={value}/>
|
43
73
|
<div>
|
44
74
|
<EventsList events={events} />
|
45
75
|
<LoadMore {...this.props} />
|
@@ -58,53 +88,16 @@ export class EventsSearch extends Component {
|
|
58
88
|
}
|
59
89
|
|
60
90
|
isFetchingFirstPage () {
|
61
|
-
|
91
|
+
this.props.xhrStatus.isFetchingEvents &&
|
62
92
|
this.props.events.length === 0
|
63
93
|
}
|
64
94
|
}
|
65
95
|
|
66
|
-
class LoadMore extends Component {
|
67
|
-
static get propTypes () {
|
68
|
-
return {
|
69
|
-
loadMoreSearchResults: PropTypes.func.isRequired,
|
70
|
-
xhrStatus: PropTypes.shape({ lastEventsLoadSize: PropTypes.number }).isRequired
|
71
|
-
}
|
72
|
-
}
|
73
|
-
|
74
|
-
render () {
|
75
|
-
return (
|
76
|
-
this.props.xhrStatus.lastEventsLoadSize === EVENTS_SEARCH_LIMIT &&
|
77
|
-
<RaisedButton
|
78
|
-
label='Load more'
|
79
|
-
onClick={() => this.props.loadMoreSearchResults()}
|
80
|
-
style={{margin: '10px'}}/>
|
81
|
-
)
|
82
|
-
}
|
83
|
-
}
|
84
|
-
|
85
|
-
class EmptyEvent extends Component {
|
86
|
-
static get propTypes () {
|
87
|
-
return {
|
88
|
-
events: PropTypes.array.isRequired,
|
89
|
-
isFetchingEvents: PropTypes.bool.isRequired
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
render () {
|
94
|
-
return (
|
95
|
-
this.props.events.length === 0 &&
|
96
|
-
!this.props.isFetchingEvents &&
|
97
|
-
<div className='empty-event'>
|
98
|
-
No events found
|
99
|
-
</div>
|
100
|
-
)
|
101
|
-
}
|
102
|
-
}
|
103
|
-
|
104
96
|
export default connect(
|
105
97
|
(state) => state, {
|
106
98
|
fetchSearchResults,
|
107
99
|
loadMoreSearchResults,
|
100
|
+
triggerSearch,
|
108
101
|
changeSearchInputFilterType,
|
109
102
|
changeSearchInputFilterValue,
|
110
103
|
showEventOverview
|
File without changes
|
@@ -1,13 +1,17 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import jasmineEnzyme from 'jasmine-enzyme'
|
3
|
-
import { mount } from 'enzyme'
|
4
|
-
import { EventsSearch } from 'views/events
|
3
|
+
import { mount, shallow } from 'enzyme'
|
4
|
+
import { EventsSearch } from 'views/events/search'
|
5
5
|
import getMuiTheme from 'material-ui/styles/getMuiTheme'
|
6
6
|
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
|
7
7
|
import { Provider } from 'react-redux'
|
8
8
|
import configureMockStore from 'redux-mock-store'
|
9
9
|
import thunk from 'redux-thunk'
|
10
10
|
|
11
|
+
import SearchInput from 'components/search-input'
|
12
|
+
import EventsList from 'components/events-list'
|
13
|
+
import EmptyEvent from 'components/empty-event'
|
14
|
+
|
11
15
|
const middlewares = [ thunk ]
|
12
16
|
const mockStore = configureMockStore(middlewares)
|
13
17
|
|
@@ -20,7 +24,7 @@ const mountComponent = (store, props) => mount(
|
|
20
24
|
)
|
21
25
|
|
22
26
|
describe('view <EventsSearch />', () => {
|
23
|
-
let props,
|
27
|
+
let props, store, wrapper
|
24
28
|
|
25
29
|
beforeEach(() => {
|
26
30
|
jasmineEnzyme()
|
@@ -33,41 +37,51 @@ describe('view <EventsSearch />', () => {
|
|
33
37
|
props = {
|
34
38
|
fetchSearchResults: jasmine.createSpy('fetchSearchResults'),
|
35
39
|
loadMoreSearchResults: jasmine.createSpy('loadMoreSearchResults'),
|
40
|
+
triggerSearch: jasmine.createSpy('triggerSearch'),
|
36
41
|
changeSearchInputFilterType: jasmine.createSpy('changeSearchInputFilterType'),
|
37
42
|
changeSearchInputFilterValue: jasmine.createSpy('changeSearchInputFilterValue'),
|
38
43
|
showEventOverview: jasmine.createSpy('showEventOverview'),
|
39
44
|
|
40
45
|
xhrStatus: { isFetchingEvents: false, lastEventsLoadSize: 0 },
|
41
|
-
location: { query: {} },
|
42
|
-
eventsFilters: {
|
46
|
+
location: { pathname: '', query: {} },
|
47
|
+
eventsFilters: {
|
48
|
+
type: 'foo',
|
49
|
+
value: 'bar'
|
50
|
+
},
|
43
51
|
events: [{ id: 1 }, { id: 2 }]
|
44
52
|
}
|
45
53
|
|
46
|
-
|
54
|
+
wrapper = shallow(<EventsSearch {...props} />)
|
47
55
|
})
|
48
56
|
|
49
57
|
it('renders <SearchInput />', () => {
|
50
|
-
expect(
|
58
|
+
expect(wrapper.contains(
|
59
|
+
<SearchInput triggerSearch={props.triggerSearch} filterType={props.eventsFilters.type} filterValue={props.eventsFilters.value} />
|
60
|
+
)).toEqual(true)
|
51
61
|
})
|
52
62
|
|
53
63
|
it('renders <EventsList />', () => {
|
54
|
-
expect(
|
64
|
+
expect(wrapper.contains(<EventsList events={props.events} />)).toEqual(true)
|
55
65
|
})
|
56
66
|
|
57
|
-
it('
|
58
|
-
expect(
|
67
|
+
it('renders <EmptyEvent />', () => {
|
68
|
+
expect(wrapper.contains(<EmptyEvent events={props.events} isFetchingEvents={props.xhrStatus.isFetchingEvents} />)).toEqual(true)
|
59
69
|
})
|
60
70
|
|
61
71
|
describe('when it initializes with filter type and value', () => {
|
62
72
|
beforeEach(() => {
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
props = {
|
74
|
+
...props,
|
75
|
+
location: {
|
76
|
+
pathname: '/events',
|
77
|
+
query: {
|
78
|
+
type: 'entity_id',
|
79
|
+
value: '12345'
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
mountComponent(store, props)
|
71
85
|
})
|
72
86
|
|
73
87
|
it('calls changeSearchInputFilterType with type', () => {
|
@@ -79,18 +93,14 @@ describe('view <EventsSearch />', () => {
|
|
79
93
|
})
|
80
94
|
})
|
81
95
|
|
82
|
-
describe('when events
|
96
|
+
describe('when events are empty', () => {
|
83
97
|
beforeEach(() => {
|
84
|
-
|
85
|
-
|
98
|
+
props = {...props, events: []}
|
99
|
+
mountComponent(store, props)
|
86
100
|
})
|
87
101
|
|
88
102
|
it('calls fetchSearchResults with offset 0', () => {
|
89
103
|
expect(props.fetchSearchResults).toHaveBeenCalledWith({ offset: 0 })
|
90
104
|
})
|
91
|
-
|
92
|
-
it('renders <EventsSearch.EmptyEvent />', () => {
|
93
|
-
expect(component.find('.empty-event').length).toEqual(1)
|
94
|
-
})
|
95
105
|
})
|
96
106
|
})
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React, { Component, PropTypes } from 'react'
|
2
|
+
import { connect } from 'react-redux'
|
3
|
+
import { history } from 'routes'
|
4
|
+
|
5
|
+
import { fetchFailureDetails } from 'actions/failures/details'
|
6
|
+
import FailureOverviewDialog from 'components/failure/overview-dialog'
|
7
|
+
import FailureRetryDialog from 'components/failure/retry-dialog'
|
8
|
+
|
9
|
+
class FailureShow extends Component {
|
10
|
+
static get propTypes () {
|
11
|
+
return {
|
12
|
+
fetchFailureDetails: PropTypes.func.isRequired
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
componentDidMount () {
|
17
|
+
this.props.params.id &&
|
18
|
+
this.props.fetchFailureDetails({ id: this.props.params.id })
|
19
|
+
}
|
20
|
+
|
21
|
+
componentDidUpdate (prevProps) {
|
22
|
+
if (this.isDialogClosed(prevProps)) {
|
23
|
+
history.push('/failures')
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
render () {
|
28
|
+
const details = this.props.failureDetails
|
29
|
+
const visible = !!details.id
|
30
|
+
const failure = Object.assign({ overviewVisible: visible }, details)
|
31
|
+
|
32
|
+
return (
|
33
|
+
<div className='failure-details'>
|
34
|
+
<FailureOverviewDialog failure={failure} />
|
35
|
+
<FailureRetryDialog failure={failure} />
|
36
|
+
</div>
|
37
|
+
)
|
38
|
+
}
|
39
|
+
|
40
|
+
isDialogClosed (prevProps) {
|
41
|
+
return prevProps.failureDetails.id !== undefined &&
|
42
|
+
this.props.failureDetails.id === undefined
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
export default connect(
|
47
|
+
(state) => state, {
|
48
|
+
fetchFailureDetails
|
49
|
+
}
|
50
|
+
)(FailureShow)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import React, { Component, PropTypes } from 'react'
|
2
|
+
import { connect } from 'react-redux'
|
3
|
+
|
4
|
+
import LoadMore from 'components/load-more'
|
5
|
+
import EmptyEvent from 'components/empty-event'
|
6
|
+
import FailuresList from 'components/failures-list'
|
7
|
+
import SearchInput from 'components/search-input'
|
8
|
+
import CircularProgress from 'material-ui/CircularProgress'
|
9
|
+
|
10
|
+
import { fetchSearchResults, loadMoreSearchResults, triggerSearch } from 'actions/failures/search'
|
11
|
+
import { changeSearchInputFilterType, changeSearchInputFilterValue } from 'actions/search-input-filter'
|
12
|
+
import { showEventOverview } from 'actions/event-overview'
|
13
|
+
|
14
|
+
export class FailuresSearch extends Component {
|
15
|
+
static get propTypes () {
|
16
|
+
return {
|
17
|
+
fetchSearchResults: PropTypes.func.isRequired,
|
18
|
+
loadMoreSearchResults: PropTypes.func.isRequired,
|
19
|
+
triggerSearch: PropTypes.func.isRequired,
|
20
|
+
changeSearchInputFilterType: PropTypes.func.isRequired,
|
21
|
+
changeSearchInputFilterValue: PropTypes.func.isRequired,
|
22
|
+
showEventOverview: PropTypes.func.isRequired,
|
23
|
+
|
24
|
+
xhrStatus: PropTypes.shape({
|
25
|
+
type: PropTypes.string,
|
26
|
+
value: PropTypes.string,
|
27
|
+
isFetchingEvents: PropTypes.bool
|
28
|
+
}),
|
29
|
+
|
30
|
+
eventsFilters: PropTypes.shape({
|
31
|
+
type: PropTypes.string,
|
32
|
+
value: PropTypes.string
|
33
|
+
}),
|
34
|
+
|
35
|
+
failures: PropTypes.arrayOf(
|
36
|
+
PropTypes.shape({
|
37
|
+
onShowOverview: PropTypes.func,
|
38
|
+
failure: PropTypes.shape({
|
39
|
+
id: PropTypes.number,
|
40
|
+
created_at: PropTypes.string,
|
41
|
+
group_id: PropTypes.string,
|
42
|
+
topic: PropTypes.string,
|
43
|
+
entity_id: PropTypes.string,
|
44
|
+
event_type: PropTypes.string,
|
45
|
+
event_time: PropTypes.string,
|
46
|
+
event_version: PropTypes.string,
|
47
|
+
checksum: PropTypes.string,
|
48
|
+
payload: PropTypes.object,
|
49
|
+
metadata: PropTypes.object,
|
50
|
+
error_class: PropTypes.string,
|
51
|
+
error_message: PropTypes.string,
|
52
|
+
error_backtrace: PropTypes.array
|
53
|
+
})
|
54
|
+
})
|
55
|
+
),
|
56
|
+
|
57
|
+
location: PropTypes.shape({
|
58
|
+
query: PropTypes.object
|
59
|
+
})
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
componentDidMount () {
|
64
|
+
const { type, value } = this.props.location.query
|
65
|
+
if (type && value) {
|
66
|
+
this.props.changeSearchInputFilterType(type)
|
67
|
+
this.props.changeSearchInputFilterValue(value)
|
68
|
+
}
|
69
|
+
|
70
|
+
this.props.failures.length === 0 &&
|
71
|
+
this.props.fetchSearchResults({ offset: 0 })
|
72
|
+
}
|
73
|
+
|
74
|
+
render () {
|
75
|
+
const { failures } = this.props
|
76
|
+
const { type, value } = this.props.eventsFilters
|
77
|
+
|
78
|
+
return (
|
79
|
+
<div className='failures-search'>
|
80
|
+
<SearchInput triggerSearch={this.props.triggerSearch} filterType={type} filterValue={value}/>
|
81
|
+
<div>
|
82
|
+
<FailuresList failures={failures} />
|
83
|
+
<LoadMore {...this.props} />
|
84
|
+
<EmptyEvent
|
85
|
+
events={failures}
|
86
|
+
isFetchingEvents={this.props.xhrStatus.isFetchingEvents}/>
|
87
|
+
</div>
|
88
|
+
{
|
89
|
+
this.isFetchingFirstPage() &&
|
90
|
+
<div className='page-loader'>
|
91
|
+
<CircularProgress />
|
92
|
+
</div>
|
93
|
+
}
|
94
|
+
</div>
|
95
|
+
)
|
96
|
+
}
|
97
|
+
|
98
|
+
isFetchingFirstPage () {
|
99
|
+
this.props.xhrStatus.isFetchingEvents &&
|
100
|
+
this.props.failures.length === 0
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
export default connect(
|
105
|
+
(state) => state, {
|
106
|
+
fetchSearchResults,
|
107
|
+
loadMoreSearchResults,
|
108
|
+
triggerSearch,
|
109
|
+
changeSearchInputFilterType,
|
110
|
+
changeSearchInputFilterValue,
|
111
|
+
showEventOverview
|
112
|
+
}
|
113
|
+
)(FailuresSearch)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
.failures-search {
|
2
|
+
max-width: 1020px;
|
3
|
+
min-height: 100%;
|
4
|
+
|
5
|
+
background-color: #e4e4e4;
|
6
|
+
margin: 0 auto;
|
7
|
+
padding: 20px 0;
|
8
|
+
|
9
|
+
.page-loader {
|
10
|
+
text-align: center;
|
11
|
+
padding: 50px 0;
|
12
|
+
}
|
13
|
+
|
14
|
+
.empty-event {
|
15
|
+
margin: 50px 15px 0;
|
16
|
+
font-size: 30px;
|
17
|
+
font-weight: lighter;
|
18
|
+
font-family: Roboto;
|
19
|
+
}
|
20
|
+
|
21
|
+
& > .event {
|
22
|
+
margin: 10px 10px;
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import jasmineEnzyme from 'jasmine-enzyme'
|
3
|
+
import { mount, shallow } from 'enzyme'
|
4
|
+
import { FailuresSearch } from 'views/failures/search'
|
5
|
+
import getMuiTheme from 'material-ui/styles/getMuiTheme'
|
6
|
+
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
|
7
|
+
import { Provider } from 'react-redux'
|
8
|
+
import configureMockStore from 'redux-mock-store'
|
9
|
+
import thunk from 'redux-thunk'
|
10
|
+
|
11
|
+
import SearchInput from 'components/search-input'
|
12
|
+
import FailuresList from 'components/failures-list'
|
13
|
+
import EmptyEvent from 'components/empty-event'
|
14
|
+
|
15
|
+
const middlewares = [ thunk ]
|
16
|
+
const mockStore = configureMockStore(middlewares)
|
17
|
+
|
18
|
+
const mountComponent = (store, props) => mount(
|
19
|
+
<Provider store={store}>
|
20
|
+
<MuiThemeProvider muiTheme={getMuiTheme()}>
|
21
|
+
<FailuresSearch {...props} />
|
22
|
+
</MuiThemeProvider>
|
23
|
+
</Provider>
|
24
|
+
)
|
25
|
+
|
26
|
+
describe('view <FailuresSearch />', () => {
|
27
|
+
let props, store, wrapper
|
28
|
+
|
29
|
+
beforeEach(() => {
|
30
|
+
jasmineEnzyme()
|
31
|
+
store = mockStore({
|
32
|
+
xhrStatus: {
|
33
|
+
isRetryingEvent: false
|
34
|
+
}
|
35
|
+
})
|
36
|
+
|
37
|
+
props = {
|
38
|
+
fetchSearchResults: jasmine.createSpy('fetchSearchResults'),
|
39
|
+
loadMoreSearchResults: jasmine.createSpy('loadMoreSearchResults'),
|
40
|
+
triggerSearch: jasmine.createSpy('triggerSearch'),
|
41
|
+
changeSearchInputFilterType: jasmine.createSpy('changeSearchInputFilterType'),
|
42
|
+
changeSearchInputFilterValue: jasmine.createSpy('changeSearchInputFilterValue'),
|
43
|
+
showEventOverview: jasmine.createSpy('showEventOverview'),
|
44
|
+
|
45
|
+
xhrStatus: { isFetchingEvents: false, lastEventsLoadSize: 0 },
|
46
|
+
location: { pathname: '', query: {} },
|
47
|
+
eventsFilters: {
|
48
|
+
type: 'foo',
|
49
|
+
value: 'bar'
|
50
|
+
},
|
51
|
+
failures: [{ id: 1 }, { id: 2 }]
|
52
|
+
}
|
53
|
+
|
54
|
+
wrapper = shallow(<FailuresSearch {...props} />)
|
55
|
+
})
|
56
|
+
|
57
|
+
it('renders <SearchInput />', () => {
|
58
|
+
expect(wrapper.contains(
|
59
|
+
<SearchInput triggerSearch={props.triggerSearch} filterType={props.eventsFilters.type} filterValue={props.eventsFilters.value} />)
|
60
|
+
).toEqual(true)
|
61
|
+
})
|
62
|
+
|
63
|
+
it('renders <FailuresList />', () => {
|
64
|
+
expect(wrapper.contains(<FailuresList failures={props.failures} />)).toEqual(true)
|
65
|
+
})
|
66
|
+
|
67
|
+
it('renders <EmptyEvent />', () => {
|
68
|
+
expect(wrapper.contains(<EmptyEvent events={props.failures} isFetchingEvents={props.xhrStatus.isFetchingEvents} />)).toEqual(true)
|
69
|
+
})
|
70
|
+
|
71
|
+
describe('when it initializes with filter type and value', () => {
|
72
|
+
beforeEach(() => {
|
73
|
+
props = {
|
74
|
+
...props,
|
75
|
+
location: {
|
76
|
+
pathname: '/failures',
|
77
|
+
query: {
|
78
|
+
type: 'entity_id',
|
79
|
+
value: '12345'
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
mountComponent(store, props)
|
85
|
+
})
|
86
|
+
|
87
|
+
it('calls changeSearchInputFilterType with type', () => {
|
88
|
+
expect(props.changeSearchInputFilterType).toHaveBeenCalledWith('entity_id')
|
89
|
+
})
|
90
|
+
|
91
|
+
it('calls changeSearchInputFilterValue with value', () => {
|
92
|
+
expect(props.changeSearchInputFilterValue).toHaveBeenCalledWith('12345')
|
93
|
+
})
|
94
|
+
})
|
95
|
+
|
96
|
+
describe('when events are empty', () => {
|
97
|
+
beforeEach(() => {
|
98
|
+
props = {...props, failures: []}
|
99
|
+
mountComponent(store, props)
|
100
|
+
})
|
101
|
+
|
102
|
+
it('calls fetchSearchResults with offset 0', () => {
|
103
|
+
expect(props.fetchSearchResults).toHaveBeenCalledWith({ offset: 0 })
|
104
|
+
})
|
105
|
+
})
|
106
|
+
})
|