fix: Add _number operator.

This commit is contained in:
Gervwyk 2021-07-30 17:31:54 +02:00
parent 2c1910ffa1
commit 1ca3966495
8 changed files with 344 additions and 0 deletions

View File

@ -665,6 +665,9 @@
- id: _not
type: MenuLink
pageId: _not
- id: _number
type: MenuLink
pageId: _number
- id: _nunjucks
type: MenuLink
pageId: _nunjucks

View File

@ -0,0 +1,157 @@
# Copyright 2020-2021 Lowdefy, Inc
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
_ref:
path: templates/operators.yaml.njk
transformer: templates/operatorsMethodTransformer.js
vars:
pageId: _number
pageTitle: _number
filePath: operators/_number.yaml
description: |
The `_number` operator can be used to run javascript [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) methods.
methods:
- name: EPSILON
types: |
```
(void): number
```
description: |
The `_number.EPSILON` property represents the smallest interval between two representable numbers.. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON) for more details and examples.
- name: MAX_SAFE_INTEGER
types: |
```
(void): number
```
description: |
The `_number.MAX_SAFE_INTEGER` property represents the maximum safe integer in JavaScript (2^53 - 1). [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) for more details and examples.
- name: MAX_VALUE
types: |
```
(void): number
```
description: |
The `_number.MAX_VALUE` property represents the largest positive representable number. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_VALUE) for more details and examples.
- name: MIN_SAFE_INTEGER
types: |
```
(void): number
```
description: |
The `_number.MIN_SAFE_INTEGER` property represents the minimum safe integer in JavaScript (-(2^53 - 1)). [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER) for more details and examples.
- name: MIN_VALUE
types: |
```
(void): number
```
description: |
The `_number.MIN_VALUE` property represents the smallest positive representable number — that is, the positive number closest to zero (without actually being zero). [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_VALUE) for more details and examples.
- name: NaN
types: |
```
(void): number
```
description: |
The `_number.NaN` property represents the special "Not a Number" value. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/NaN) for more details and examples.
- name: NEGATIVE_INFINITY
types: |
```
(void): number
```
description: |
The `_number.NEGATIVE_INFINITY` property represents negative infinity. Returned on overflow. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/NEGATIVE_INFINITY) for more details and examples.
- name: POSITIVE_INFINITY
types: |
```
(void): number
```
description: |
The `_number.POSITIVE_INFINITY` property represents positive infinity. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/POSITIVE_INFINITY) for more details and examples.
- name: isFinite
types: |
```
(void): number
```
description: |
The `_number.isFinite` method is used to determine whether the passed value is a finite number. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite) for more details and examples.
- name: isInteger
types: |
```
(void): number
```
description: |
The `_number.isInteger` method is used to determine whether the passed value is an integer. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger) for more details and examples.
- name: isNaN
types: |
```
(void): number
```
description: |
The `_number.isNaN` method is used to determine whether the passed value is NaN. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) for more details and examples.
- name: isSafeInteger
types: |
```
(void): number
```
description: |
The `_number.isSafeInteger` method is used to determine whether the passed value is a safe integer (number between -(2^53 - 1) and 2^53 - 1). [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger) for more details and examples.
- name: parseFloat
types: |
```
(void): number
```
description: |
The `_number.parseFloat` method parses an argument and returns a floating point number. If a number cannot be parsed from the argument, it returns NaN. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseFloat) for more details and examples.
- name: parseInt
types: |
```
(void): number
```
description: |
The `_number.parseInt` method parses a string argument and returns an integer of the specified radix or base. If a number cannot be parsed from the argument, it returns NaN. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseInt) for more details and examples.
- name: toExponential
types: |
```
(void): number
```
description: |
The `_number.toExponential` method returns a string representing the Number object in exponential notation. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toExponential) for more details and examples.
- name: toFixed
types: |
```
(void): number
```
description: |
The `_number.toFixed` method formats a number using fixed-point notation. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) for more details and examples.
- name: toLocaleString
types: |
```
(void): number
```
description: |
The `_number.toLocaleString` method returns a string with a language-sensitive representation of this number. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString) for more details and examples.
- name: toPrecision
types: |
```
(void): number
```
description: |
The `_number.toPrecision` method returns a string representing the Number object to the specified precision. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) for more details and examples.
- name: toString
types: |
```
(void): number
```
description: |
The `_number.toString` method returns a string representing the specified Number object. [See MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString) for more details and examples.

View File

@ -183,6 +183,7 @@
- _ref: operators/_mql.yaml
- _ref: operators/_ne.yaml
- _ref: operators/_not.yaml
- _ref: operators/_number.yaml
- _ref: operators/_nunjucks.yaml
- _ref: operators/_object.yaml
- _ref: operators/_operator.yaml

View File

@ -40,6 +40,7 @@ export default {
_mql: 'common/mql',
_ne: 'common/ne',
_not: 'common/not',
_number: 'common/number',
_nunjucks: 'common/nunjucks',
_object: 'common/object',
_operator: 'common/operator',

View File

@ -0,0 +1,65 @@
/*
Copyright 2020-2021 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import runClass from '../runClass';
import runInstance from '../runInstance';
const meta = {
EPSILON: { property: true },
MAX_SAFE_INTEGER: { property: true },
MAX_VALUE: { property: true },
MIN_SAFE_INTEGER: { property: true },
MIN_VALUE: { property: true },
NaN: { property: true },
NEGATIVE_INFINITY: { property: true },
POSITIVE_INFINITY: { property: true },
isFinite: { singleArg: true },
isInteger: { singleArg: true },
isNaN: { singleArg: true },
isSafeInteger: { singleArg: true },
parseFloat: { singleArg: true, validTypes: ['string'] },
parseInt: { namedArgs: ['on', 'radix'], validTypes: ['array', 'object'] },
toExponential: { namedArgs: ['on', 'fractionDigits'], validTypes: ['array', 'object'] },
toFixed: { namedArgs: ['on', 'digits'], validTypes: ['array', 'object'] },
toLocaleString: { namedArgs: ['on', 'locales'], validTypes: ['array', 'object'] },
toPrecision: { namedArgs: ['on', 'precision'], validTypes: ['array', 'object'] },
toString: { namedArgs: ['on', 'radix'], validTypes: ['array', 'object'] },
};
function _number({ params, location, methodName }) {
if (
['toExponential', 'toFixed', 'toLocaleString', 'toPrecision', 'toString'].includes(methodName)
) {
return runInstance({
location,
meta: meta,
methodName,
operator: '_number',
params,
instanceType: 'number',
});
}
return runClass({
functions: Number,
location,
meta: meta,
methodName,
operator: '_number',
params,
});
}
export default _number;

View File

@ -496,4 +496,13 @@ describe('parse operators', () => {
expect(res.output).toEqual('testString');
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('parse _number operator', async () => {
const input = { '_number.toFixed': { on: 12.33666, digits: 2 } };
const parser = new NodeParser({ state });
await parser.init();
const res = parser.parse({ input, location: 'locationId' });
expect(res.output).toEqual(12.34);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
});

View File

@ -547,4 +547,13 @@ describe('parse operators', () => {
expect(res.output).toEqual('testString');
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
test('parse _number operator', async () => {
const input = { '_number.toFixed': { on: 12.33666, digits: 2 } };
const parser = new WebParser({ context, contexts });
await parser.init();
const res = parser.parse({ input, location: 'locationId' });
expect(res.output).toEqual(12.34);
expect(res.errors).toMatchInlineSnapshot(`Array []`);
});
});

View File

@ -0,0 +1,99 @@
/*
Copyright 2020-2021 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import _number from '../../src/common/number';
test('_number called with no method or params', () => {
expect(() => _number({ location: 'locationId' })).toThrowErrorMatchingInlineSnapshot(`
"Operator Error: _number requires a valid method name, use one of the following: EPSILON, MAX_SAFE_INTEGER, MAX_VALUE, MIN_SAFE_INTEGER, MIN_VALUE, NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY, isFinite, isInteger, isNaN, isSafeInteger, parseFloat, parseInt, toExponential, toFixed, toLocaleString, toPrecision, toString.
Received: {\\"_number.undefined\\":undefined} at locationId."
`);
});
test('_number invalid method or params', () => {
expect(() => _number({ params: 'X', location: 'locationId' }))
.toThrowErrorMatchingInlineSnapshot(`
"Operator Error: _number requires a valid method name, use one of the following: EPSILON, MAX_SAFE_INTEGER, MAX_VALUE, MIN_SAFE_INTEGER, MIN_VALUE, NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY, isFinite, isInteger, isNaN, isSafeInteger, parseFloat, parseInt, toExponential, toFixed, toLocaleString, toPrecision, toString.
Received: {\\"_number.undefined\\":\\"X\\"} at locationId."
`);
});
test('_number invalid method', () => {
expect(() => _number({ params: [1], methodName: 'X', location: 'locationId' }))
.toThrowErrorMatchingInlineSnapshot(`
"Operator Error: _number.X is not supported, use one of the following: EPSILON, MAX_SAFE_INTEGER, MAX_VALUE, MIN_SAFE_INTEGER, MIN_VALUE, NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY, isFinite, isInteger, isNaN, isSafeInteger, parseFloat, parseInt, toExponential, toFixed, toLocaleString, toPrecision, toString.
Received: {\\"_number.X\\":[1]} at locationId."
`);
});
test('_number invalid method args', () => {
expect(() => _number({ params: 'X', methodName: 'toFixed', location: 'locationId' }))
.toThrowErrorMatchingInlineSnapshot(`
"Operator Error: _number.toFixed accepts one of the following types: array, object.
Received: {\\"_number.toFixed\\":\\"X\\"} at locationId."
`);
});
test('_number valid functions', () => {
expect(
_number({ methodName: 'toExponential', params: [77.1234, 2], location: 'locationId' })
).toBe('7.71e+1');
expect(_number({ methodName: 'toFixed', params: [12.3456, 2], location: 'locationId' })).toBe(
'12.35'
);
expect(
_number({ methodName: 'toLocaleString', params: [123456.789, 'de-DE'], location: 'locationId' })
).toBe('123.456,789');
expect(
_number({ methodName: 'toPrecision', params: [5.123456, 2], location: 'locationId' })
).toBe('5.1');
expect(_number({ methodName: 'toString', params: [5.1], location: 'locationId' })).toBe('5.1');
expect(_number({ methodName: 'EPSILON', params: [true], location: 'locationId' })).toBe(
Number.EPSILON
);
expect(_number({ methodName: 'MAX_SAFE_INTEGER', params: [true], location: 'locationId' })).toBe(
Number.MAX_SAFE_INTEGER
);
expect(_number({ methodName: 'MAX_VALUE', params: [true], location: 'locationId' })).toBe(
Number.MAX_VALUE
);
expect(_number({ methodName: 'MIN_SAFE_INTEGER', params: [true], location: 'locationId' })).toBe(
Number.MIN_SAFE_INTEGER
);
expect(_number({ methodName: 'MIN_VALUE', params: [true], location: 'locationId' })).toBe(
Number.MIN_VALUE
);
expect(_number({ methodName: 'NaN', params: [true], location: 'locationId' })).toBe(Number.NaN);
expect(_number({ methodName: 'NEGATIVE_INFINITY', params: [true], location: 'locationId' })).toBe(
Number.NEGATIVE_INFINITY
);
expect(_number({ methodName: 'POSITIVE_INFINITY', params: [true], location: 'locationId' })).toBe(
Number.POSITIVE_INFINITY
);
expect(_number({ methodName: 'isFinite', params: 2e64, location: 'locationId' })).toBe(true);
expect(_number({ methodName: 'isInteger', params: -100000, location: 'locationId' })).toBe(true);
expect(_number({ methodName: 'isNaN', params: NaN, location: 'locationId' })).toBe(true);
expect(_number({ methodName: 'isSafeInteger', params: 3, location: 'locationId' })).toBe(true);
expect(_number({ methodName: 'isSafeInteger', params: Infinity, location: 'locationId' })).toBe(
false
);
expect(
_number({ methodName: 'parseFloat', params: '4.567abcdefgh', location: 'locationId' })
).toBe(4.567);
expect(_number({ methodName: 'parseInt', params: [' 0xF', 16], location: 'locationId' })).toBe(
15
);
});