From 34a2e23dc616c1b07b61fa2e9f92709f2361fa2f Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Wed, 22 Feb 2023 01:20:07 +0530 Subject: [PATCH] feat: assertion operator in UI --- .../Assertions/AssertionOperator/index.js | 76 ++++++++ .../Assertions/AssertionRow/index.js | 164 ++++++++++++++++++ .../{Assert => Assertions}/StyledWrapper.js | 2 +- .../{Assert => Assertions}/index.js | 59 ++----- .../RequestPane/HttpRequestPane/index.js | 4 +- .../bruno-js/src/runtime/assert-runtime.js | 14 +- 6 files changed, 259 insertions(+), 60 deletions(-) create mode 100644 packages/bruno-app/src/components/RequestPane/Assertions/AssertionOperator/index.js create mode 100644 packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js rename packages/bruno-app/src/components/RequestPane/{Assert => Assertions}/StyledWrapper.js (97%) rename packages/bruno-app/src/components/RequestPane/{Assert => Assertions}/index.js (52%) diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/AssertionOperator/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionOperator/index.js new file mode 100644 index 00000000..993eb791 --- /dev/null +++ b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionOperator/index.js @@ -0,0 +1,76 @@ +import React from 'react'; + +/** + * Assertion operators + * + * eq : equal to + * neq : not equal to + * gt : greater than + * gte : greater than or equal to + * lt : less than + * lte : less than or equal to + * in : in + * notIn : not in + * contains : contains + * notContains : not contains + * length : length + * matches : matches + * notMatches : not matches + * startsWith : starts with + * endsWith : ends with + * between : between + * isEmpty : is empty + * isNull : is null + * isUndefined : is undefined + * isDefined : is defined + * isTruthy : is truthy + * isFalsy : is falsy + * isJson : is json + * isNumber : is number + * isString : is string + * isBoolean : is boolean + */ + +const AssertionOperator = ({ operator, onChange }) => { + const operators = [ + 'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', + 'contains', 'notContains', 'length', 'matches', 'notMatches', + 'startsWith', 'endsWith', 'between', 'isEmpty', 'isNull', 'isUndefined', + 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' + ]; + + const handleChange = (e) => { + onChange(e.target.value); + }; + + const getLabel = (operator) => { + switch(operator) { + case 'eq': + return 'equals'; + case 'neq': + return 'notEquals'; + case 'gt': + return 'greaterThan'; + case 'gte': + return 'greaterThanOrEqual'; + case 'lt': + return 'lessThan'; + case 'lte': + return 'lessThanOrEqual'; + default: + return operator; + } + }; + + return ( + + ); +}; + +export default AssertionOperator; diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js new file mode 100644 index 00000000..bbf18ad0 --- /dev/null +++ b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js @@ -0,0 +1,164 @@ +import React from 'react'; +import { IconTrash } from '@tabler/icons'; +import SingleLineEditor from 'components/SingleLineEditor'; +import AssertionOperator from '../AssertionOperator'; +import { useTheme } from 'providers/Theme'; + +/** + * Assertion operators + * + * eq : equal to + * neq : not equal to + * gt : greater than + * gte : greater than or equal to + * lt : less than + * lte : less than or equal to + * in : in + * notIn : not in + * contains : contains + * notContains : not contains + * length : length + * matches : matches + * notMatches : not matches + * startsWith : starts with + * endsWith : ends with + * between : between + * isEmpty : is empty + * isNull : is null + * isUndefined : is undefined + * isDefined : is defined + * isTruthy : is truthy + * isFalsy : is falsy + * isJson : is json + * isNumber : is number + * isString : is string + * isBoolean : is boolean + */ +const parseAssertionOperator = (str = '') => { + if(!str || typeof str !== 'string' || !str.length) { + return { + operator: 'eq', + value: str + }; + } + + const operators = [ + 'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', + 'contains', 'notContains', 'length', 'matches', 'notMatches', + 'startsWith', 'endsWith', 'between', 'isEmpty', 'isNull', 'isUndefined', + 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' + ]; + + const unaryOperators = [ + 'isEmpty', 'isNull', 'isUndefined', 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' + ]; + + const [operator, ...rest] = str.trim().split(' '); + const value = rest.join(' '); + + if(unaryOperators.includes(operator)) { + return { + operator, + value: '' + }; + } + + if(operators.includes(operator)) { + return { + operator, + value + }; + } + + return { + operator: 'eq', + value: str + }; +}; + +const isUnaryOperator = (operator) => { + const unaryOperators = [ + 'isEmpty', 'isNull', 'isUndefined', 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean' + ]; + + return unaryOperators.includes(operator); +}; + +const AssertionRow = ({ + item, collection, assertion, handleAssertionChange, handleRemoveAssertion, + onSave, handleRun +}) => { + const { storedTheme } = useTheme(); + + const { + operator, + value + } = parseAssertionOperator(assertion.value); + console.log(operator); + console.log(value); + + return ( + + + handleAssertionChange(e, assertion, 'name')} + /> + + + handleAssertionChange({ + target: { + value: `${op} ${value}` + } + }, assertion, 'value')} + /> + + + {!isUnaryOperator(operator) ? ( + handleAssertionChange({ + target: { + value: newValue + } + }, assertion, 'value')} + onRun={handleRun} + collection={collection} + /> + ) : ( + + )} + + +
+ handleAssertionChange(e, assertion, 'enabled')} + /> + +
+ + + ); +}; + +export default AssertionRow; diff --git a/packages/bruno-app/src/components/RequestPane/Assert/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js similarity index 97% rename from packages/bruno-app/src/components/RequestPane/Assert/StyledWrapper.js rename to packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js index b7c95b47..7357a74b 100644 --- a/packages/bruno-app/src/components/RequestPane/Assert/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js @@ -24,7 +24,7 @@ const Wrapper = styled.div` width: 30%; } - &:nth-child(3) { + &:nth-child(4) { width: 70px; } } diff --git a/packages/bruno-app/src/components/RequestPane/Assert/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/index.js similarity index 52% rename from packages/bruno-app/src/components/RequestPane/Assert/index.js rename to packages/bruno-app/src/components/RequestPane/Assertions/index.js index 256a77c9..1805a632 100644 --- a/packages/bruno-app/src/components/RequestPane/Assert/index.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/index.js @@ -1,17 +1,14 @@ import React from 'react'; import get from 'lodash/get'; import cloneDeep from 'lodash/cloneDeep'; -import { IconTrash } from '@tabler/icons'; import { useDispatch } from 'react-redux'; -import { useTheme } from 'providers/Theme'; import { addAssertion, updateAssertion, deleteAssertion } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; -import SingleLineEditor from 'components/SingleLineEditor'; +import AssertionRow from './AssertionRow'; import StyledWrapper from './StyledWrapper'; const Assertions = ({ item, collection }) => { const dispatch = useDispatch(); - const { storedTheme } = useTheme(); const assertions = item.draft ? get(item, 'draft.request.assertions') : get(item, 'request.assertions'); const handleAddAssertion = () => { @@ -66,55 +63,25 @@ const Assertions = ({ item, collection }) => { Expr + Operator Value {assertions && assertions.length - ? assertions.map((assertion, index) => { + ? assertions.map((assertion) => { return ( - - - handleAssertionChange(e, assertion, 'name')} - /> - - - handleAssertionChange({ - target: { - value: newValue - } - }, assertion, 'value')} - onRun={handleRun} - collection={collection} - /> - - -
- handleAssertionChange(e, assertion, 'enabled')} - /> - -
- - + ); }) : null} diff --git a/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js b/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js index 5ddf2393..55da6c9c 100644 --- a/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js +++ b/packages/bruno-app/src/components/RequestPane/HttpRequestPane/index.js @@ -8,7 +8,7 @@ import RequestHeaders from 'components/RequestPane/RequestHeaders'; import RequestBody from 'components/RequestPane/RequestBody'; import RequestBodyMode from 'components/RequestPane/RequestBody/RequestBodyMode'; import Vars from 'components/RequestPane/Vars'; -import Assert from 'components/RequestPane/Assert'; +import Assertions from 'components/RequestPane/Assertions'; import Script from 'components/RequestPane/Script'; import Tests from 'components/RequestPane/Tests'; import StyledWrapper from './StyledWrapper'; @@ -42,7 +42,7 @@ const HttpRequestPane = ({ item, collection, leftPaneWidth }) => { return ; } case 'assert': { - return ; + return ; } case 'script': { return