Skip to content

Commit 37be329

Browse files
pzrqrueckstiess
authored andcommitted
COMPASS 156 Range Component - queryToParams (#546)
* COMPASS 156: DV - range component queryToParams Revert "Revert "Temporarily add range rule in" so partial progress stays hidden" This reverts commit cb9a1cc. * Migrate validation.rule.test.js into Compass CI tests * Move validation.store.test.js into CI tests, skipping errors I don't understand where these are coming from, so skip them for now as it's unclear if we might want to go back to a separate shareable repo in future: FIRST ERROR -------------------- ✓ goes into {fetchState: "error"} when receiving an error back TypeError: Cannot set property 'validator' of undefined at Store._deconstructValidatorDoc (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:81:7) at _fetchFromServer (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:223:27) at Timeout._onTimeout (/Users/pzrq/Projects/compass/test/validation.store.test.js:14:14) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) TypeError: Cannot set property 'validator' of undefined at Store._deconstructValidatorDoc (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:81:7) at _fetchFromServer (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:223:27) at Timeout._onTimeout (/Users/pzrq/Projects/compass/test/validation.store.test.js:14:14) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) 1) goes into {fetchState: "error"} when receiving an invalid validator doc Failed with exit code: 1 SECOND ERROR ------------------------- ✓ goes into {fetchState: "error"} when receiving an error back - goes into {fetchState: "error"} when receiving an invalid validator doc TypeError: Cannot set property 'validator' of undefined at Store._deconstructValidatorDoc (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:81:7) at _fetchFromServer (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:223:27) at Timeout._onTimeout (/Users/pzrq/Projects/compass/test/validation.store.test.js:14:14) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) TypeError: Cannot set property 'validator' of undefined at Store._deconstructValidatorDoc (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:81:7) at _fetchFromServer (/Users/pzrq/Projects/compass/src/internal-packages/validation/lib/stores/index.js:223:27) at Timeout._onTimeout (/Users/pzrq/Projects/compass/test/validation.store.test.js:14:14) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) 1) goes into {fetchState: "error"} when the result is not an object { AssertionError: expected 1 to equal 2 at Timeout.setTimeout (/Users/pzrq/Projects/compass/test/validation.store.test.js:110:35) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) message: 'expected 1 to equal 2', showDiff: true, actual: 1, expected: 2 } AssertionError: expected 1 to equal 2 at Timeout.setTimeout (/Users/pzrq/Projects/compass/test/validation.store.test.js:110:35) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) 2) "after each" hook * Migrate range code and tests from compass-validation repo * Refactor logic into validateKeyAndValue Lowers the complexity of queryToParams from 14 to 12. * Remove chained if to lower complexity Fixes TODO. * Drop infinity support and add some negative and decimals tests Infinity is dropped as the empty clause is better and so we don't have to represent it in the GUI. * Improve test context * Get values from an existing validatorDoc shown in GUI At a mongo shell: use validation; > db.runCommand({collMod: 'validation', validator: {"age": {$gte:0.01,$lt:5000 }, "phone_no": { "$regex": "^[0-9 ]+$", "$options": "mx" } }}); * Get {<, <=, >, >=, none} server validatorDoc shown in dropdown GUI At a mongo shell: use validation; > db.runCommand({collMod: 'validation', validator: {"age": {$gte:0.01,$lt:5000 }, "phone_no": { "$regex": "^[0-9 ]+$", "$options": "mx" } }}); * Hide range component again and skip integration tests Full range component to come in a JIRA linked to COMPASS-156 or COMPASS-235. * Structure & naming things request from @rueckstiess, thanks! * Skip things again Coming in COMPASS-235, definitely working on that today so we can stop this back and forth partial stuff. * Drop unnecessary skips * fix “fetching” test, allow callback to be called once * Fix RangeInput test warnings about missing non-default required "value" * Drop "are not useful" Wasn't found in earlier string replace in COMPASS-156
1 parent d653b06 commit 37be329

File tree

5 files changed

+387
-18
lines changed

5 files changed

+387
-18
lines changed

src/internal-packages/validation/lib/components/common/range-input.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ class RangeInput extends React.Component {
167167
}
168168

169169
RangeInput.propTypes = {
170-
value: React.PropTypes.number,
170+
value: React.PropTypes.number.isRequired,
171171
upperBound: React.PropTypes.bool,
172172
validationState: React.PropTypes.string,
173-
boundIncluded: React.PropTypes.bool,
174-
disabled: React.PropTypes.bool,
173+
boundIncluded: React.PropTypes.bool.isRequired,
174+
disabled: React.PropTypes.bool.isRequired,
175175
onChange: React.PropTypes.func,
176176
width: React.PropTypes.number
177177
};

src/internal-packages/validation/lib/components/rule-categories/range.jsx

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,26 @@ class RuleCategoryRange extends React.Component {
4343
return result;
4444
}
4545

46+
static validateKeyAndValue(key, value) {
47+
if (!_.includes(['$gt', '$gte', '$lt', '$lte'], key)) {
48+
return false;
49+
}
50+
// Check that we have only numeric (or null) types.
51+
// String types are a possible extension,
52+
// but documents, arrays, BinData, undefined and other BSON types
53+
// make little sense http://bsonspec.org/spec.html
54+
if (typeof(value) !== 'number') {
55+
return false;
56+
}
57+
return !isNaN(value) && Math.abs(value) !== Infinity;
58+
}
59+
4660
static queryToParams(query) {
4761
// if not every key in the object is one of the comparison operators,
4862
// this rule cannot represent the query
4963
const keys = _.keys(query);
5064
if (!_.every(keys, (key) => {
51-
return _.contains(['$gt', '$gte', '$lt', '$lte'], key);
65+
return RuleCategoryRange.validateKeyAndValue(key, query[key]);
5266
})) {
5367
return false;
5468
}
@@ -58,12 +72,17 @@ class RuleCategoryRange extends React.Component {
5872
lowerBoundValue: query.$gte || query.$gt || null,
5973
lowerBoundType: _.intersection(keys, ['$gte', '$gt'])
6074
};
61-
62-
if (result.upperBoundType.length === 0) {
63-
result.upperBoundType = null;
75+
if (result.upperBoundType.length > 1 || result.lowerBoundType.length > 1) {
76+
return false;
6477
}
65-
if (result.lowerBoundType.length === 0) {
66-
result.lowerBoundType = null;
78+
result.upperBoundType = result.upperBoundType[0] || null;
79+
result.lowerBoundType = result.lowerBoundType[0] || null;
80+
81+
// No documents could possibly satisfy these cases, e.g. 5 <= value < 5
82+
if (typeof(result.upperBoundValue) === 'number' &&
83+
typeof(result.lowerBoundValue) === 'number' &&
84+
result.upperBoundValue <= result.lowerBoundValue) {
85+
return false;
6786
}
6887
return result;
6988
}
@@ -76,8 +95,17 @@ class RuleCategoryRange extends React.Component {
7695
render() {
7796
return (
7897
<FormGroup>
79-
<RangeInput />
80-
<RangeInput upperBound/>
98+
<RangeInput
99+
boundIncluded={this.props.parameters.lowerBoundType === '$gte'}
100+
disabled={this.props.parameters.lowerBoundType === null}
101+
value={this.props.parameters.lowerBoundValue}
102+
/>
103+
<RangeInput
104+
upperBound
105+
boundIncluded={this.props.parameters.upperBoundType === '$lte'}
106+
disabled={this.props.parameters.upperBoundType === null}
107+
value={this.props.parameters.upperBoundValue}
108+
/>
81109
</FormGroup>
82110
);
83111
}

test/validation.range.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,25 @@ chai.use(chaiEnzyme());
1515
describe('<RangeInput />', () => {
1616
context('when rendering the default control', () => {
1717
it('has label `LOWER BOUND`', () => {
18-
const component = shallow(<RangeInput />);
18+
const component = shallow(<RangeInput value={5} />);
1919
const labelText = component.find(ControlLabel).dive().text();
2020
expect(labelText).to.be.equal('LOWER BOUND');
2121
});
2222
it('has placeholder text of `enter lower bound`', () => {
23-
const component = shallow(<RangeInput />);
23+
const component = shallow(<RangeInput value={5} />);
2424
const placeholderText = component.find(FormControl).props().placeholder;
2525
expect(placeholderText).to.be.equal('enter lower bound');
2626
});
2727
});
2828

2929
context('when rendering an upperBound control', () => {
3030
it('has label `UPPER BOUND`', () => {
31-
const component = shallow(<RangeInput upperBound />);
31+
const component = shallow(<RangeInput upperBound value={5} />);
3232
const labelText = component.find(ControlLabel).dive().text();
3333
expect(labelText).to.be.equal('UPPER BOUND');
3434
});
3535
it('has placeholder text of `enter upper bound`', () => {
36-
const component = shallow(<RangeInput upperBound />);
36+
const component = shallow(<RangeInput upperBound value={5} />);
3737
const placeholderText = component.find(FormControl).props().placeholder;
3838
expect(placeholderText).to.be.equal('enter upper bound');
3939
});

src/internal-packages/validation/test/rule.test.js renamed to test/validation.rule.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
/* eslint no-unused-expressions: 0 */
1+
/* eslint no-unused-vars: 0 */
22
const chai = require('chai');
33
const chaiEnzyme = require('chai-enzyme');
44
const expect = chai.expect;
55
const React = require('react');
66

77
const mount = require('enzyme').mount;
8-
const Rule = require('../lib/components/rule');
8+
const Rule = require('../src/internal-packages/validation/lib/components/rule');
99
const _ = require('lodash');
1010

1111
// const debug = require('debug')('compass:validation:test');

0 commit comments

Comments
 (0)