Skip to content

Commit

Permalink
added hasCategory and hasOperator functions to auto complete handlers…
Browse files Browse the repository at this point in the history
…. fixed strict mode bug and added validateQuery unit tests.
  • Loading branch information
wetzelb committed Jul 29, 2020
1 parent 5dc0727 commit a1cefac
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 6 deletions.
8 changes: 8 additions & 0 deletions src/BaseAutoCompleteHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ export default class BaseAutoCompleteHandler {
})
}

hasCategory(category: string): boolean {
return false;
}

hasOperator(category: string, operator: string): boolean {
return false;
}

needCategories(): string[] {
return []
}
Expand Down
12 changes: 12 additions & 0 deletions src/GridDataAutoCompleteHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ export default class GridDataAutoCompleteHandler extends BaseAutoCompleteHandler
});
}

hasCategory(category: string): boolean {
var found = _.find(this.options, f => {
return (category === f.columnField || category === f.columnText);
});

return found !== undefined;
}

hasOperator(category: string, operator: string): boolean {
return this.needOperators(category).indexOf(operator) >= 0;
}

needCategories() {
return this.categories;
}
Expand Down
10 changes: 6 additions & 4 deletions src/ReactFilterBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ export default class ReactFilterBox extends React.Component<any, any> {
return this.props.onParseError(result, { isValid: true });
} else if (this.props.strictMode) {
const validationResult = validateQuery(result as Expression[], this.parser.autoCompleteHandler);
return this.props.onParseError(result, validationResult);
if (!validationResult.isValid) {
return this.props.onParseError(result, validationResult);
}
}

return this.props.onParseOk(result);
Expand All @@ -64,10 +66,10 @@ export default class ReactFilterBox extends React.Component<any, any> {
if ((result as ParsedError).isError) {
this.setState({ isError: true })
} else if (this.props.strictMode) {
validationResult = validateQuery(result as Expression[], this.parser.autoCompleteHandler);
this.setState({ isError: !validationResult.isValid })
validationResult = validateQuery(result as Expression[], this.parser.autoCompleteHandler);
this.setState({ isError: !validationResult.isValid })
} else {
this.setState({ isError: false })
this.setState({ isError: false })
}

this.props.onChange(query, result, validationResult);
Expand Down
4 changes: 2 additions & 2 deletions src/validateQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ const validateExpression = (
const expressions = expression.expressions;

if (expressions === undefined) {
if (autoCompleteHandler.needCategories().indexOf(expression.category) < 0) {
if (autoCompleteHandler.hasCategory(expression.category) === false) {
result = {
isValid: false,
message: `Invalid category '${expression.category}' in expression ${expression.category} ${expression.operator} ${expression.value}`
};
} else if (autoCompleteHandler.needOperators(expression.category).indexOf(expression.operator) < 0) {
} else if (autoCompleteHandler.hasOperator(expression.category, expression.operator) === false) {
result = {
isValid: false,
message: `Invalid operator '${expression.operator}' in expression ${expression.category} ${expression.operator} ${expression.value}`
Expand Down
229 changes: 229 additions & 0 deletions test/validateQuery.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import { expect } from 'chai';
import validateQuery from "../src/validateQuery";
import Expression from "../src/Expression";
import GridDataAutoCompleteHandler, { Option } from '../src/GridDataAutoCompleteHandler';
// import sinon = require("sinon");

describe("#validateQuery", () => {

// common fixture data
var options: Option[] = [
{
columnField: 'column1',
columnText: 'Column1',
type: 'text'
},
{
columnField: 'column2',
type: 'text'
},
{
columnField: 'column3',
columnText: 'Column3',
type: 'text',
customOperatorFunc: (category: string): string[] => {
return ['**', 'in'];
}
}
];
var autoCompleteHandler = new GridDataAutoCompleteHandler([], options);

describe("#category validation (all operators are valid)", () => {

it("with catogory matching columnField should return isValid set to true", () => {
var expression: Expression[] = [
{
category: 'column2',
operator: '==',
}
];

var result = validateQuery(expression, autoCompleteHandler);
console.log(result);
expect(result.isValid).to.be.true;
});

it("with catogory matching columnText should return isValid set to true", () => {
var expression: Expression[] = [
{
category: 'Column1',
operator: '==',
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.true;
});

it("with non-matching category should return isValid set to false and set message", () => {
var expression: Expression[] = [
{
category: 'FakeColumn1',
operator: '==',
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.false;
expect(result.message.indexOf('Invalid category')).to.eq(0);
});
});

describe("#operator validation (all categories are valid)", () => {
it("with matching operator should return isValid set to true", () => {
var expression: Expression[] = [
{
category: 'Column1',
operator: '==',
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.true;
});

it("with matching against custom operator function should return isValid set to true", () => {
var expression: Expression[] = [
{
category: 'Column3',
operator: '**',
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.true;
});

it("with non-matching operator should return isValid set to false and set message", () => {
var expression: Expression[] = [
{
category: 'column1',
operator: '=',
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.false;
expect(result.message.indexOf('Invalid operator')).to.eq(0);
});

it("with non-matching custom operator should return isValid set to false and set message", () => {
var expression: Expression[] = [
{
category: 'column3',
operator: '==',
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.false;
expect(result.message.indexOf('Invalid operator')).to.eq(0);
});
});

describe("#complex expression", () => {
it("query with two conditions should return isValid set to true", () => {
var expression: Expression[] = [
{
conditionType: 'OR',
expressions: [
{
category: 'column2',
operator: '==',
},
{
category: 'column3',
operator: '**',
}
]
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.true;
});

it("query with two invalid conditions should return isValid set to false", () => {
var expression: Expression[] = [
{
conditionType: 'OR',
expressions: [
{
category: 'column4', // invalid column
operator: '==',
},
{
category: 'column3',
operator: '<>', // invalid operator
}
]
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.false;
expect(result.message.indexOf('Invalid category')).to.eq(0);
});

it("valid query with nested conditions should return isValid set to true", () => {
var expression: Expression[] = [
{
conditionType: 'OR',
expressions: [
{
category: 'column1',
operator: '==',
},
{
conditionType: 'AND',
expressions: [
{
category: 'column2',
operator: 'contains',
},
{
category: 'column3',
operator: 'in',
}
]
}
]
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.true;
});

it("query with invalid nested condition should return isValid set to false", () => {
var expression: Expression[] = [
{
conditionType: 'OR',
expressions: [
{
category: 'column1',
operator: '==',
},
{
conditionType: 'AND',
expressions: [
{
category: 'column2',
operator: 'contains',
},
{
category: 'column3',
operator: '==', // invalid operator
}
]
}
]
}
];

var result = validateQuery(expression, autoCompleteHandler);
expect(result.isValid).to.be.false;
expect(result.message.indexOf('Invalid operator')).to.eq(0);
});
});
});

0 comments on commit a1cefac

Please sign in to comment.