Skip to content

Commit 55f2d35

Browse files
committedSep 2, 2016
closes #228. implement required filters. default filter operator is now =. filter button is now a submit button
1 parent 9349c4f commit 55f2d35

File tree

7 files changed

+272
-195
lines changed

7 files changed

+272
-195
lines changed
 

‎package.json

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
"isomorphic-fetch": "^2.2.1",
6464
"leaflet": "^0.7.7",
6565
"leaflet-fullscreen": "^1.0.1",
66+
"lodash.isequal": "^4.4.0",
67+
"lodash.uniqby": "^4.7.0",
6668
"material-ui": "^0.15.4",
6769
"morgan": "^1.7.0",
6870
"numeral": "^1.5.3",

‎src/js/components/Dashboard.jsx

+72-34
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import {connect} from 'react-redux'
2-
import {excludeEmptyFilters} from '../modules/utilities'
32
import {fetchVisualizationResults} from '../modules/visualization-results'
43
import FilterCriteria from './FilterCriteria'
54
import {Hydrateable} from '../decorators/Hydrateable'
65
import {LogMetrics} from '../decorators'
6+
import {setDefaultFilters} from '../modules/filters'
7+
import uniqBy from 'lodash.uniqby'
78
import {verticalTop} from '../styles/common'
89
import Visualization from './visualization/Visualization'
10+
import {createFilter, excludeEmptyFilters, validateFilters} from '../modules/utilities'
911
import React, {Component, PropTypes} from 'react'
1012
import ReactGridLayout, {WidthProvider} from 'react-grid-layout'
11-
import {resetFilters, setDefaultFilters} from '../modules/filters'
1213

1314
const GridLayout = WidthProvider(ReactGridLayout)
1415
const gridMargin = 10
@@ -44,22 +45,79 @@ class Dashboard extends Component {
4445
constructor (props) {
4546
super(props)
4647

47-
this.onClickFilter = ::this.onClickFilter
48+
this.onClickSubmit = ::this.onClickSubmit
4849
this.onClickReset = ::this.onClickReset
4950
}
5051

5152
componentWillMount () {
52-
const {dashboard, dispatch} = this.props
53+
this.resetFilters()
54+
}
5355

54-
const {dashboardParams = {}} = dashboard
55-
const {filters: dashboardFilters = []} = dashboardParams
56+
validateFilters = () => {
57+
const {filters} = this.props
58+
59+
return validateFilters(filters)
60+
}
61+
62+
getUniqueFields = () => {
63+
const {dashboard: {visualizations}} = this.props
64+
const sources = visualizations.map((visualization) => visualization.source)
5665

57-
if (dashboardFilters && dashboardFilters.length > 0) {
58-
dispatch(setDefaultFilters(dashboardFilters))
66+
return uniqBy(sources.reduce((fields, source) => (
67+
[...fields, ...source.fields]
68+
)), 'name')
69+
}
70+
71+
getOptionalFilters = (requiredFilters, dashboardFilters) => {
72+
const optional = dashboardFilters.filter((filter) => {
73+
return !requiredFilters.find((requiredFilter) => {
74+
return requiredFilter.field === filter.field
75+
})
76+
})
77+
78+
if (optional.length === 0) {
79+
optional.push(createFilter())
5980
}
81+
82+
return optional
83+
}
84+
85+
getRequiredFilters = (requiredFields, dashboardFilters) => {
86+
return requiredFields
87+
.map((field) => {
88+
let newFilter = createFilter({
89+
field: field.name,
90+
required: true
91+
})
92+
const existingFilter = dashboardFilters.find((filter) => {
93+
return filter.field === field
94+
})
95+
96+
if (existingFilter) {
97+
newFilter = Object.assign({}, newFilter, existingFilter)
98+
}
99+
100+
return newFilter
101+
})
102+
}
103+
104+
resetFilters () {
105+
const {dashboard, dispatch} = this.props
106+
const {dashboardParams = {}} = dashboard
107+
const {filters: dashboardFilters = []} = dashboardParams
108+
const fields = this.getUniqueFields()
109+
const requiredFields = fields.filter((field) => field.required)
110+
const required = this.getRequiredFilters(requiredFields, dashboardFilters)
111+
const optional = this.getOptionalFilters(required, dashboardFilters)
112+
113+
dispatch(
114+
setDefaultFilters(
115+
required.concat(optional)
116+
)
117+
)
60118
}
61119

62-
onClickFilter () {
120+
onClickSubmit () {
63121
const {dispatch, filters, dashboard} = this.props
64122
const {visualizations} = dashboard
65123

@@ -77,22 +135,7 @@ class Dashboard extends Component {
77135
}
78136

79137
onClickReset () {
80-
const {dispatch, dashboard} = this.props
81-
82-
const {dashboardParams = {}} = dashboard
83-
const {filters: dashboardFilters = []} = dashboardParams
84-
85-
if (dashboardFilters && dashboardFilters.length > 0) {
86-
dispatch(resetFilters(dashboardFilters))
87-
} else {
88-
const filter = {
89-
field: '',
90-
operator: '',
91-
value: ''
92-
}
93-
94-
dispatch(resetFilters([filter]))
95-
}
138+
this.resetFilters()
96139
}
97140

98141
renderVisualizationGrid () {
@@ -152,18 +195,12 @@ class Dashboard extends Component {
152195
return null
153196
}
154197

155-
const {_id, title, visualizations} = dashboard
198+
const {_id, title} = dashboard
156199

157200
// Populate the Fields based off of the fields
158201
// for each visualization's source.
159202
const fields = {
160-
data: [...(new Set(visualizations.reduce(
161-
(array, visualization) => {
162-
const {fields = []} = visualization.source
163-
164-
return [...array, ...fields]
165-
}, []
166-
)))],
203+
data: this.getUniqueFields(),
167204
isFetching: false
168205
}
169206

@@ -182,8 +219,9 @@ class Dashboard extends Component {
182219
...verticalTop,
183220
marginBottom: '1em'
184221
}}
185-
onClickFilter={this.onClickFilter}
222+
valid={this.validateFilters()}
186223
onClickReset={this.onClickReset}
224+
onClickSubmit={this.onClickSubmit}
187225
/>
188226
{this.renderVisualizationGrid()}
189227
</div>

‎src/js/components/FilterCriteria.jsx

+130-99
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import CardExpandable from 'material-ui/Card/CardExpandable'
33
import {connect} from 'react-redux'
44
import ContentAdd from 'material-ui/svg-icons/content/add'
55
import ContentRemove from 'material-ui/svg-icons/content/remove'
6-
import {excludeEmptyFilters} from '../modules/utilities'
76
import FloatingActionButton from 'material-ui/FloatingActionButton'
7+
import isEqual from 'lodash.isequal'
88
import MetricsWrapper from './MetricsWrapper'
99
import {operators} from '../constants'
1010
import RaisedButton from 'material-ui/RaisedButton'
@@ -13,6 +13,7 @@ import TextField from 'material-ui/TextField'
1313
import Tooltip from './Tooltip'
1414
import {verticalTop} from '../styles/common'
1515
import {addFilter, editFilter, removeFilter} from '../modules/filters'
16+
import {createFilter, excludeEmptyFilters} from '../modules/utilities'
1617
import {cyan500, grey400, redA400} from 'material-ui/styles/colors.js'
1718
import React, {Component, PropTypes} from 'react'
1819

@@ -55,18 +56,21 @@ class FilterCriteria extends Component {
5556
headerText: PropTypes.string,
5657
label: PropTypes.string,
5758
style: PropTypes.object,
59+
valid: PropTypes.boolean,
5860
wrapperStyle: PropTypes.object,
59-
onClickFilter: PropTypes.func,
60-
onClickReset: PropTypes.func
61+
onClickReset: PropTypes.func,
62+
onClickSubmit: PropTypes.func
6163
}
6264

6365
static defaultProps = {
6466
criteriaDataProperty: 'data',
6567
headerStyle: {},
66-
headerText: 'Select filter criteria (optional)',
67-
onClickFilter: null,
68+
headerText: 'Select filter criteria',
6869
style: {},
69-
wrapperStyle: {}
70+
valid: true,
71+
wrapperStyle: {},
72+
onClickReset: () => {},
73+
onClickSubmit: () => {}
7074
}
7175

7276
constructor (props) {
@@ -84,15 +88,78 @@ class FilterCriteria extends Component {
8488
this.toggle = ::this.toggle
8589
}
8690

91+
createFilterElement = (filter, i, isFirstOptionalFilter) => {
92+
const {
93+
criteriaDataProperty,
94+
fields,
95+
style: filterStyle
96+
} = this.props
97+
const field = fields.data[filter.fieldIndex] || {}
98+
const {[criteriaDataProperty]: criteriaData} = field
99+
const ValueField = criteriaData ? AutoComplete : TextField
100+
const filterIndex = this.getFilterIndex(filter)
101+
const errorText = filter.required && !filter.value
102+
? 'Required'
103+
: undefined
104+
105+
return (
106+
<div key={filterIndex}>
107+
<SelectField
108+
disabled={filter.required}
109+
floatingLabelText='Select a field'
110+
hintText='Select a field'
111+
isFetching={fields.isFetching}
112+
items={fields.data}
113+
keyProp={'name'}
114+
primaryTextProp={'name'}
115+
style={verticalTop}
116+
value={filter.field}
117+
valueProp={'name'}
118+
onChange={(ev, index, value) => this.onChangeField(ev, filterIndex, value, index)}
119+
/>
120+
<SelectField
121+
floatingLabelText='Select an operator'
122+
hintText='Select an operator'
123+
items={operators}
124+
keyProp={'value'}
125+
primaryTextProp={'primaryText'}
126+
style={verticalTop}
127+
value={filter.operator}
128+
valueProp={'value'}
129+
onChange={(ev, index, value) => this.onChangeOperator(ev, filterIndex, value, index)}
130+
/>
131+
<ValueField
132+
dataSource={criteriaData}
133+
errorText={errorText}
134+
filter={AutoComplete.caseInsensitiveFilter}
135+
floatingLabelText='Filter Criteria'
136+
hintText='Filter Criteria'
137+
openOnFocus={true}
138+
style={filterStyle}
139+
value={filter.value}
140+
onChange={(ev) => this.onChangeValue(ev, filterIndex)}
141+
/>
142+
{(() => {
143+
if (filter.required) {
144+
return null
145+
}
146+
147+
return [
148+
isFirstOptionalFilter
149+
? null
150+
: this.renderRemoveButton(filterIndex),
151+
this.renderAddButton()
152+
]
153+
})()}
154+
</div>
155+
)
156+
}
157+
87158
onAddFilter (ev) {
88159
const {dispatch} = this.props
89160

90161
ev.preventDefault()
91-
dispatch(addFilter({
92-
field: '',
93-
operator: '',
94-
value: ''
95-
}))
162+
dispatch(addFilter(createFilter()))
96163
}
97164

98165
onChangeField (ev, index, field, fieldIndex) {
@@ -155,14 +222,22 @@ class FilterCriteria extends Component {
155222
})
156223
}
157224

225+
getFilterIndex (filter) {
226+
const {filters} = this.props
227+
228+
return filters.findIndex((currentFilter) => {
229+
return isEqual(currentFilter, filter)
230+
})
231+
}
232+
158233
handleClickFilter (...params) {
159-
const {onClickFilter} = this.props
234+
const {onClickSubmit} = this.props
160235

161236
if (this.state.expanded) {
162237
this.toggle()
163238
}
164239

165-
onClickFilter(...params)
240+
onClickSubmit(...params)
166241
}
167242

168243
handleClickReset (...params) {
@@ -171,10 +246,8 @@ class FilterCriteria extends Component {
171246
onClickReset(...params)
172247
}
173248

174-
renderAddButton (i) {
175-
const {filters, style: filterStyle} = this.props
176-
177-
if (i !== filters.length - 1) return null
249+
renderAddButton () {
250+
const {style: filterStyle} = this.props
178251

179252
return (
180253
<Tooltip
@@ -197,52 +270,26 @@ class FilterCriteria extends Component {
197270
</Tooltip>
198271
)
199272
}
200-
201-
renderRemoveButton (i) {
202-
const {filters, style: filterStyle} = this.props
203-
204-
if (filters.length === 1) return null
205-
206-
return (
207-
<Tooltip
208-
label='Click to remove this filter'
209-
style={{
210-
...style.filterButton
211-
}}
212-
>
213-
<FloatingActionButton
214-
mini={true}
215-
primary={true}
216-
style={{
217-
...filterStyle,
218-
...style.filterButton
219-
}}
220-
onTouchTap={(ev) => this.onRemoveFilter(ev, i)}
221-
>
222-
<ContentRemove />
223-
</FloatingActionButton>
224-
</Tooltip>
225-
)
226-
}
227273

228274
renderButtons () {
229275
const {expanded} = this.state
230276
const {
231277
filters,
232278
label,
233-
onClickFilter,
279+
onClickSubmit,
234280
style: filterStyle
235281
} = this.props
236282
const searchFilters = excludeEmptyFilters(filters)
237283

238-
if (!expanded || !onClickFilter) return null
284+
if (!expanded || !onClickSubmit) return null
239285

240286
return (
241287
<span>
242288
<MetricsWrapper
243289
component={
244290
<RaisedButton
245-
label='Filter'
291+
disabled={!this.props.valid}
292+
label='Submit'
246293
primary={true}
247294
style={filterStyle.button}
248295
/>}
@@ -264,69 +311,53 @@ class FilterCriteria extends Component {
264311

265312
renderFilters () {
266313
const {expanded} = this.state
314+
const {filters} = this.props
315+
const required = filters.filter((filter) => filter.required)
316+
const optional = filters.filter((filter) => !filter.required)
267317

268318
if (!expanded) return null
269319

270-
const {filters} = this.props
320+
return required.concat(optional).map((filter, i, array) => (
321+
this.createFilterElement(
322+
filter,
323+
i,
324+
i === Math.abs(array.length - required.length - (optional.length - 1))
325+
)
326+
))
327+
}
271328

272-
return filters.map((filter, i) => {
273-
const {
274-
criteriaDataProperty,
275-
fields,
276-
style: filterStyle
277-
} = this.props
278-
const field = fields.data[filter.fieldIndex] || {}
279-
const {[criteriaDataProperty]: criteriaData} = field
280-
const ValueField = criteriaData ? AutoComplete : TextField
329+
// (i) is the index of the filter in filters
330+
renderRemoveButton (i) {
331+
const {style: filterStyle} = this.props
281332

282-
return (
283-
<div key={i}>
284-
<SelectField
285-
floatingLabelText='Select a field'
286-
hintText='Select a field'
287-
isFetching={fields.isFetching}
288-
items={fields.data}
289-
keyProp={'name'}
290-
primaryTextProp={'name'}
291-
style={verticalTop}
292-
value={filter.field}
293-
valueProp={'name'}
294-
onChange={(ev, index, value) => this.onChangeField(ev, i, value, index)}
295-
/>
296-
<SelectField
297-
floatingLabelText='Select an operator'
298-
hintText='Select an operator'
299-
items={operators}
300-
keyProp={'value'}
301-
primaryTextProp={'primaryText'}
302-
style={verticalTop}
303-
value={filter.operator}
304-
valueProp={'value'}
305-
onChange={(ev, index, value) => this.onChangeOperator(ev, i, value, index)}
306-
/>
307-
<ValueField
308-
dataSource={criteriaData}
309-
filter={AutoComplete.caseInsensitiveFilter}
310-
floatingLabelText='Filter Criteria'
311-
hintText='Filter Criteria'
312-
openOnFocus={true}
313-
style={filterStyle}
314-
value={filter.value}
315-
onChange={(ev) => this.onChangeValue(ev, i)}
316-
/>
317-
{this.renderRemoveButton(i)}
318-
{this.renderAddButton(i)}
319-
</div>
320-
)
321-
})
333+
return (
334+
<Tooltip
335+
label='Click to remove this filter'
336+
style={{
337+
...style.filterButton
338+
}}
339+
>
340+
<FloatingActionButton
341+
mini={true}
342+
primary={true}
343+
style={{
344+
...filterStyle,
345+
...style.filterButton
346+
}}
347+
onTouchTap={(ev) => this.onRemoveFilter(ev, i)}
348+
>
349+
<ContentRemove />
350+
</FloatingActionButton>
351+
</Tooltip>
352+
)
322353
}
323354

324355
render () {
325356
const {
326357
fields,
327358
headerStyle,
328359
headerText,
329-
onClickFilter,
360+
onClickSubmit,
330361
wrapperStyle
331362
} = this.props
332363

@@ -342,7 +373,7 @@ class FilterCriteria extends Component {
342373
<div style={wrapperStyle}>
343374
<h3 style={headerStyle}>
344375
{headerText}
345-
{onClickFilter
376+
{onClickSubmit
346377
? <CardExpandable
347378
expanded={this.state.expanded}
348379
style={style.expandButton}

‎src/js/components/Search.jsx

+16-25
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import {connect} from 'react-redux'
2+
import {excludeEmptyFilters} from '../modules/utilities'
23
import {fetchFields} from '../modules/fields'
34
import {fetchSearchResults} from '../modules/search-results'
45
import {fetchSources} from '../modules/sources'
56
import FilterCriteria from './FilterCriteria'
6-
import MetricsWrapper from './MetricsWrapper'
7-
import RaisedButton from 'material-ui/RaisedButton'
7+
// import MetricsWrapper from './MetricsWrapper'
8+
// import RaisedButton from 'material-ui/RaisedButton'
9+
import {resetFilters} from '../modules/filters'
810
import {setSource} from '../modules/source'
911
import {CircularProgress, DataTable, SelectField} from 'safe-framework'
10-
import {excludeEmptyFilters, getNameByID} from '../modules/utilities'
1112
import {grey300, white} from 'material-ui/styles/colors'
1213
import {header, main, verticalTop} from '../styles/common'
1314
import {Hydrateable, LogMetrics} from '../decorators'
@@ -37,6 +38,7 @@ const style = {
3738
background: white,
3839
border: `1px solid ${grey300}`,
3940
height: '510px',
41+
margin: '.5em 0 0 0',
4042
position: 'relative'
4143
}
4244
}
@@ -74,7 +76,7 @@ class Search extends Component {
7476
columns: []
7577
}
7678
this.onChangeSource = ::this.onChangeSource
77-
this.onClickSearch = ::this.onClickSearch
79+
this.onClickSubmit = ::this.onClickSubmit
7880
}
7981

8082
updateColumns (data) {
@@ -150,26 +152,27 @@ class Search extends Component {
150152
)
151153
}
152154

153-
onClickSearch () {
155+
onClickReset = () => {
156+
const {dispatch} = this.props
157+
158+
dispatch(resetFilters())
159+
}
160+
161+
onClickSubmit () {
154162
const {dispatch, filters, source} = this.props
155-
163+
156164
dispatch(fetchSearchResults(source, excludeEmptyFilters(filters)))
157165
}
158166

159167
render () {
160168
const {
161169
fields,
162-
filters,
163170
source,
164171
sources
165172
} = this.props
166173
const filterStyle = source === ''
167174
? style.hidden
168175
: {}
169-
170-
const sourceName = getNameByID(sources.data, source)
171-
const label = source === '' ? 'Search' : `Search_${sourceName}_${source}`
172-
const searchFilters = excludeEmptyFilters(filters)
173176

174177
return (
175178
<div>
@@ -193,21 +196,9 @@ class Search extends Component {
193196
fields={fields}
194197
style={verticalTop}
195198
wrapperStyle={filterStyle}
199+
onClickReset={this.onClickReset}
200+
onClickSubmit={this.onClickSubmit}
196201
/>
197-
<div>
198-
<MetricsWrapper
199-
component={
200-
<RaisedButton
201-
disabled={!source}
202-
label='Search'
203-
primary={true}
204-
style={style.button}
205-
/>}
206-
data={{filters: searchFilters}}
207-
label={label}
208-
onTouchTap={this.onClickSearch}
209-
/>
210-
</div>
211202
{this.renderSearchResults()}
212203
</main>
213204
</div>

‎src/js/modules/filters.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import {excludeEmptyFilters} from './utilities'
2-
31
export const ADD = 'safe-app/filters/ADD'
42
export const EDIT = 'safe-app/filters/EDIT'
53
export const HYDRATE = 'safe-app/filters/HYDRATE'
@@ -27,8 +25,7 @@ export const removeFilter = (index) => ({
2725
payload: {index}
2826
})
2927

30-
export const resetFilters = (filters) => ({
31-
payload: {filters},
28+
export const resetFilters = () => ({
3229
type: RESET
3330
})
3431

@@ -41,13 +38,14 @@ let nextFilterId = 0
4138
const initialState = [{
4239
id: nextFilterId,
4340
field: '',
44-
operator: '',
41+
operator: '=',
42+
required: false,
4543
value: ''
4644
}]
4745

4846
export default (state = initialState, {payload = {}, type, ...action}) => {
4947
const {filter, filters, index, value} = payload
50-
48+
5149
switch (type) {
5250
case ADD:
5351
return [
@@ -72,11 +70,13 @@ export default (state = initialState, {payload = {}, type, ...action}) => {
7270
...state.slice(index + 1)
7371
]
7472
case RESET:
75-
return [...filters]
73+
const newFilters = [...initialState]
74+
75+
newFilters[0].id = ++nextFilterId
76+
77+
return newFilters
7678
case SET_DEFAULT:
77-
return excludeEmptyFilters(state).length === 0
78-
? [...filters]
79-
: state
79+
return [...filters]
8080
case HYDRATE:
8181
return [...state]
8282
default:

‎src/js/modules/utilities.jsx

+20-3
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ export const getNameByID = (list, id) => {
9898
if (list.length === 0 || id === '') {
9999
return ''
100100
}
101-
101+
102102
for (const item of list) {
103103
const {_id, name} = item
104-
104+
105105
if (_id === id) {
106106
return name
107107
}
@@ -127,4 +127,21 @@ export const getValueByPath = (object, path) => {
127127
})
128128

129129
return currentValue
130-
}
130+
}
131+
132+
export const createFilter = (filter = {}) => {
133+
const initialValue = {
134+
field: '',
135+
operator: '=',
136+
required: false,
137+
value: ''
138+
}
139+
140+
return Object.assign({}, initialValue, filter)
141+
}
142+
143+
export const validateFilters = (filters = []) => (
144+
filters.filter((filter) => {
145+
return filter.required && (!filter.operator || !filter.value)
146+
}).length === 0
147+
)

‎test/modules/filters.spec.js

+22-24
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,11 @@ describe('filter actions', () => {
7171
})
7272

7373
it('resetFilters should create a RESET action', () => {
74-
const filters = [{
75-
id: 0,
76-
field: 'FieldA',
77-
operator: '=',
78-
value: 'FieldAValue'
79-
}]
80-
8174
const expectedAction = {
82-
type: RESET,
83-
payload: {filters}
75+
type: RESET
8476
}
8577

86-
expect(resetFilters(filters)).toEqual(expectedAction)
78+
expect(resetFilters()).toEqual(expectedAction)
8779
})
8880

8981
it('setDefaultFilters should create a SET_DEFAULT action', () => {
@@ -105,13 +97,17 @@ describe('filter actions', () => {
10597
describe('filters reducer', () => {
10698
it('should return the initial state', () => {
10799
const stateAfter = [{
108-
id: 0,
109100
field: '',
110-
operator: '',
101+
operator: '=',
102+
required: false,
111103
value: ''
112104
}]
113105

114-
expect(reducer(undefined, {})).toEqual(stateAfter)
106+
const result = reducer(undefined, {})
107+
108+
stateAfter[0].id = result[0].id
109+
110+
expect(result).toEqual(stateAfter)
115111
})
116112

117113
it('should handle ADD', () => {
@@ -216,22 +212,24 @@ describe('filters reducer', () => {
216212
operator: '<=',
217213
value: 'fieldBValue'
218214
}]
219-
const filters = [{
220-
id: 0,
221-
field: 'fieldA',
222-
operator: '=',
223-
value: 'fieldAValue'
224-
}]
225215
const action = {
226-
payload: {filters},
227216
type: RESET
228217
}
229-
const stateAfter = [...filters]
218+
const stateAfter = [{
219+
field: '',
220+
operator: '=',
221+
required: false,
222+
value: ''
223+
}]
230224

231225
deepFreeze(stateBefore)
232226
deepFreeze(action)
233227

234-
expect(reducer(stateBefore, action)).toEqual(stateAfter)
228+
const result = reducer(stateBefore, action)
229+
230+
stateAfter[0].id = result[0].id
231+
232+
expect(result).toEqual(stateAfter)
235233
})
236234

237235
it('should handle SET_DEFAULT when no filters exist', () => {
@@ -262,7 +260,7 @@ describe('filters reducer', () => {
262260
it('should handle SET_DEFAULT when filters exist', () => {
263261
const stateBefore = [{
264262
id: 0,
265-
field: 'FieldB',
263+
field: 'Field',
266264
operator: '=',
267265
value: 'FieldBValue'
268266
}]
@@ -276,7 +274,7 @@ describe('filters reducer', () => {
276274
payload: {filters},
277275
type: SET_DEFAULT
278276
}
279-
const stateAfter = [...stateBefore]
277+
const stateAfter = [...filters]
280278

281279
deepFreeze(stateBefore)
282280
deepFreeze(action)

0 commit comments

Comments
 (0)
Please sign in to comment.