Add tabIndex attribute to all tags with an onClick attribute (+ ran npx prettier --write ./packages to address warnings)

This commit is contained in:
Gareth B. 2024-07-20 16:44:37 +00:00
parent e5b8a11cbb
commit 822cc5524b
123 changed files with 7398 additions and 3150 deletions

View File

@ -1638,7 +1638,7 @@ const make_ssf = function make_ssf(SSF) {
throw new Error("cannot find right format for |" + fmt.join("|") + "|");
// 这行代码弃用有可能v会有"1"的情况出现并且需要排查truefalse 这些值所以需要使用parseFloat(v).toString()去判断是不是Number类型
// if (typeof v !== "number")
if(parseFloat(v).toString() == "NaN")
if (parseFloat(v).toString() == "NaN")
return [4, fmt.length === 4 || lat > -1 ? fmt[fmt.length - 1] : "@"];
switch (fmt.length) {
case 1:
@ -1717,15 +1717,15 @@ const make_ssf = function make_ssf(SSF) {
if (vlength > 4) {
if (vlength > 8) {
var y = parseInt(v / 100000000); //亿
var w = parseInt(parseFloat(v)-(y * 100000000) / 10000); //万
var q = parseFloat(v)-(y * 100000000 + w * 10000); //千以后
var w = parseInt(parseFloat(v) - (y * 100000000) / 10000); //万
var q = parseFloat(v) - (y * 100000000 + w * 10000); //千以后
if (acc != "") {
q = numeral(q).format(acc); //处理精确度
}
v = y + "亿" + w + "万" + q;
} else {
var w = parseInt(v / 10000); //万
var q = parseFloat(v)-(w * 10000); //千以后
var q = parseFloat(v) - w * 10000; //千以后
if (acc != "") {
q = numeral(q).format(acc); //处理精确度
}

View File

@ -1,19 +1,25 @@
{
"presets": [
["@babel/preset-env", {
modules: false,
}]
[
"@babel/preset-env",
{
"modules": false
}
]
],
"env": {
"commonjs": {
"plugins": [
["@babel/plugin-transform-modules-commonjs", { loose: true }]
["@babel/plugin-transform-modules-commonjs", { "loose": true }]
]
},
"es": {
"plugins": [
["./.config/plugin/babel/add-import-extension.js", { extension: "mjs" }]
[
"./.config/plugin/babel/add-import-extension.js",
{ "extension": "mjs" }
]
]
},
}
}
}

View File

@ -4,24 +4,24 @@ engines:
enabled: true
config:
languages:
- ruby
- javascript
- python
- php
- ruby
- javascript
- python
- php
eslint:
enabled: true
fixme:
enabled: true
ratings:
paths:
- "**.inc"
- "**.js"
- "**.jsx"
- "**.module"
- "**.php"
- "**.py"
- "**.rb"
- "**.inc"
- "**.js"
- "**.jsx"
- "**.module"
- "**.php"
- "**.py"
- "**.rb"
exclude_paths:
- dist/
- test/
- src/grammar-parser/
- dist/
- test/
- src/grammar-parser/

View File

@ -1,34 +1,42 @@
const { types } = require('@babel/core');
const { declare } = require('@babel/helper-plugin-utils');
const { existsSync, lstatSync } = require('fs');
const { dirname, resolve } = require('path');
const { types } = require("@babel/core");
const { declare } = require("@babel/helper-plugin-utils");
const { existsSync, lstatSync } = require("fs");
const { dirname, resolve } = require("path");
const VALID_EXTENSIONS = ['js', 'mjs'];
const VALID_EXTENSIONS = ["js", "mjs"];
const hasExtension = (moduleName) => VALID_EXTENSIONS.some(ext => moduleName.endsWith(`.${ext}`));
const isCoreJSPolyfill = (moduleName) => moduleName.startsWith('core-js');
const isLocalModule = (moduleName) => moduleName.startsWith('.');
const hasExtension = (moduleName) =>
VALID_EXTENSIONS.some((ext) => moduleName.endsWith(`.${ext}`));
const isCoreJSPolyfill = (moduleName) => moduleName.startsWith("core-js");
const isLocalModule = (moduleName) => moduleName.startsWith(".");
const isNodeModule = (moduleName) => {
try {
require.resolve(moduleName);
return true;
} catch (ex) {
if (ex.code === 'MODULE_NOT_FOUND') {
if (ex.code === "MODULE_NOT_FOUND") {
return false;
}
}
};
const isProcessableModule = (moduleName) => {
return !hasExtension(moduleName) && (isCoreJSPolyfill(moduleName) || isLocalModule(moduleName));
}
return (
!hasExtension(moduleName) &&
(isCoreJSPolyfill(moduleName) || isLocalModule(moduleName))
);
};
const createVisitor = ({ declaration, origArgs, extension = 'js' }) => {
const createVisitor = ({ declaration, origArgs, extension = "js" }) => {
return (path, { file }) => {
const { node: { source, exportKind, importKind } } = path;
const { opts: { filename } } = file;
const isTypeOnly = exportKind === 'type' || importKind === 'type';
const {
node: { source, exportKind, importKind },
} = path;
const {
opts: { filename },
} = file;
const isTypeOnly = exportKind === "type" || importKind === "type";
if (!source || isTypeOnly || !isProcessableModule(source.value)) {
return;
@ -36,7 +44,7 @@ const createVisitor = ({ declaration, origArgs, extension = 'js' }) => {
const { value: moduleName } = source;
const absoluteFilePath = resolve(dirname(filename), moduleName);
const finalExtension = isCoreJSPolyfill(moduleName) ? 'js' : extension;
const finalExtension = isCoreJSPolyfill(moduleName) ? "js" : extension;
let newModulePath;
@ -59,17 +67,22 @@ const createVisitor = ({ declaration, origArgs, extension = 'js' }) => {
if (existsSync(`${absoluteFilePath}.js`)) {
newModulePath = `${moduleName}.${finalExtension}`;
// In a case when the file doesn't exist and the module is a directory it will
// rename to `plugins/index.js`.
} else if (existsSync(absoluteFilePath) && lstatSync(absoluteFilePath).isDirectory()) {
newModulePath = `${moduleName}/index.${finalExtension}`;
// In a case when the file doesn't exist and the module is a directory it will
// rename to `plugins/index.js`.
} else if (
existsSync(absoluteFilePath) &&
lstatSync(absoluteFilePath).isDirectory()
) {
newModulePath = `${moduleName}/index.${finalExtension}`;
// And for other cases it simply put the extension on the end of the module path
// And for other cases it simply put the extension on the end of the module path
} else {
newModulePath = `${moduleName}.${finalExtension}`;
}
path.replaceWith(declaration(...origArgs(path), types.stringLiteral(newModulePath)));
path.replaceWith(
declaration(...origArgs(path), types.stringLiteral(newModulePath))
);
};
};
@ -77,7 +90,7 @@ module.exports = declare((api, options) => {
api.assertVersion(7);
return {
name: 'add-import-extension',
name: "add-import-extension",
visitor: {
// It covers default and named imports
ImportDeclaration: createVisitor({
@ -88,13 +101,16 @@ module.exports = declare((api, options) => {
ExportNamedDeclaration: createVisitor({
extension: options.extension,
declaration: types.exportNamedDeclaration,
origArgs: ({ node: { declaration, specifiers } }) => [declaration, specifiers],
origArgs: ({ node: { declaration, specifiers } }) => [
declaration,
specifiers,
],
}),
ExportAllDeclaration: createVisitor({
extension: options.extension,
declaration: types.exportAllDeclaration,
origArgs: () => [],
}),
}
},
};
});

View File

@ -1,5 +1,5 @@
export default {
target: 'browser',
target: "browser",
cjs: { type: "babel", lazy: true },
esm: { type: "babel" },
disableTypeCheck: false,

View File

@ -5,17 +5,8 @@
"skip_git_push": false,
"release_message": true,
"remote": "origin",
"pre_commit_commands": [
"npm run clean",
"npm run build",
"npm run test"
],
"pre_commit_commands": ["npm run clean", "npm run build", "npm run test"],
"post_commit_commands": [],
"post_complete_commands": [
"cd tmp && npm publish",
"npm run clean"
],
"files_to_commit": [
"./dist/**/*"
]
"post_complete_commands": ["cd tmp && npm publish", "npm run clean"],
"files_to_commit": ["./dist/**/*"]
}

View File

@ -3,7 +3,7 @@ language: node_js
sudo: false
node_js:
- '10'
- "10"
install:
- npm ci

View File

@ -1,13 +1,12 @@
:warning: This repository is deprecated. We've released new and improved [HyperFormula](https://github.com/handsontable/hyperformula/) engine.
<details>
Formula Parser [![Build Status](https://travis-ci.org/handsontable/formula-parser.png?branch=master)](https://travis-ci.org/handsontable/formula-parser) [![Test Coverage](https://codeclimate.com/github/handsontable/formula-parser/badges/coverage.svg)](https://codeclimate.com/github/handsontable/formula-parser/coverage) [![hot-formula-parser](https://img.shields.io/npm/v/hot-formula-parser.svg)](https://www.npmjs.com/package/hot-formula-parser)
==========
# Formula Parser [![Build Status](https://travis-ci.org/handsontable/formula-parser.png?branch=master)](https://travis-ci.org/handsontable/formula-parser) [![Test Coverage](https://codeclimate.com/github/handsontable/formula-parser/badges/coverage.svg)](https://codeclimate.com/github/handsontable/formula-parser/coverage) [![hot-formula-parser](https://img.shields.io/npm/v/hot-formula-parser.svg)](https://www.npmjs.com/package/hot-formula-parser)
Library provides a `Parser` class that evaluates excel and mathematical formulas.
- - -
---
## Install
@ -18,38 +17,41 @@ $ npm install hot-formula-parser --save
```
Node.js:
```js
var FormulaParser = require('hot-formula-parser').Parser;
var FormulaParser = require("hot-formula-parser").Parser;
var parser = new FormulaParser();
parser.parse('SUM(1, 6, 7)'); // It returns `Object {error: null, result: 14}`
parser.parse("SUM(1, 6, 7)"); // It returns `Object {error: null, result: 14}`
```
Browser:
```html
<script src="/node_modules/hot-formula-parser/dist/formula-parser.min.js"></script>
<script>
var parser = new formulaParser.Parser();
var parser = new formulaParser.Parser();
parser.parse('SUM(1, 6, 7)'); // It returns `Object {error: null, result: 14}`
parser.parse("SUM(1, 6, 7)"); // It returns `Object {error: null, result: 14}`
</script>
```
## Features
It supports:
* Any numbers, negative and positive as float or integer;
* Arithmetic operations like `+`, `-`, `/`, `*`, `%`, `^`;
* Logical operations like `AND()`, `OR()`, `NOT()`, `XOR()`;
* Comparison operations like `=`, `>`, `>=`, `<`, `<=`, `<>`;
* All JavaScript Math constants like `PI()`, `E()`, `LN10()`, `LN2()`, `LOG10E()`, `LOG2E()`, `SQRT1_2()`, `SQRT2()`;
* String operations like `&` (concatenation eq. `parser.parse('-(2&5)');` will return `-25`);
* All excel formulas defined in [formula.js](https://github.com/handsontable/formula.js);
* Relative and absolute cell coordinates like `A1`, `$A1`, `A$1`, `$A$1`;
* Build-in variables like `TRUE`, `FALSE`, `NULL`
* Custom variables;
* Custom functions/formulas;
* Node and Browser environment.
- Any numbers, negative and positive as float or integer;
- Arithmetic operations like `+`, `-`, `/`, `*`, `%`, `^`;
- Logical operations like `AND()`, `OR()`, `NOT()`, `XOR()`;
- Comparison operations like `=`, `>`, `>=`, `<`, `<=`, `<>`;
- All JavaScript Math constants like `PI()`, `E()`, `LN10()`, `LN2()`, `LOG10E()`, `LOG2E()`, `SQRT1_2()`, `SQRT2()`;
- String operations like `&` (concatenation eq. `parser.parse('-(2&5)');` will return `-25`);
- All excel formulas defined in [formula.js](https://github.com/handsontable/formula.js);
- Relative and absolute cell coordinates like `A1`, `$A1`, `A$1`, `$A$1`;
- Build-in variables like `TRUE`, `FALSE`, `NULL`
- Custom variables;
- Custom functions/formulas;
- Node and Browser environment.
## API (methods)
@ -61,17 +63,18 @@ var parser = new formulaParser.Parser();
Parses and evaluates provided expression. It always returns an object with `result` and `error` properties. `result` property
always keep evaluated value. If error occurs `error` property will be set as:
* `#ERROR!` General error;
* `#DIV/0!` Divide by zero error;
* `#NAME?` Not recognised function name or variable name;
* `#N/A` Indicates that a value is not available to a formula;
* `#NUM!` Occurs when formula encounters an invalid number;
* `#VALUE!` Occurs when one of formula arguments is of the wrong type.
- `#ERROR!` General error;
- `#DIV/0!` Divide by zero error;
- `#NAME?` Not recognised function name or variable name;
- `#N/A` Indicates that a value is not available to a formula;
- `#NUM!` Occurs when formula encounters an invalid number;
- `#VALUE!` Occurs when one of formula arguments is of the wrong type.
```js
parser.parse('(1 + 5 + (5 * 10)) / 10'); // returns `Object {error: null, result: 5.6}`
parser.parse('SUM(MY_VAR)'); // returns `Object {error: "#NAME?", result: null}`
parser.parse('1;;1'); // returns `Object {error: "#ERROR!", result: null}`
parser.parse("(1 + 5 + (5 * 10)) / 10"); // returns `Object {error: null, result: 5.6}`
parser.parse("SUM(MY_VAR)"); // returns `Object {error: "#NAME?", result: null}`
parser.parse("1;;1"); // returns `Object {error: "#ERROR!", result: null}`
```
### .setVariable(name, value)
@ -79,10 +82,10 @@ parser.parse('1;;1'); // returns `Object {error: "#ERROR!", result: null}`
Set predefined variable name which can be visible while parsing formula expression.
```js
parser.setVariable('MY_VARIABLE', 5);
parser.setVariable('fooBar', 10);
parser.setVariable("MY_VARIABLE", 5);
parser.setVariable("fooBar", 10);
parser.parse('(1 + MY_VARIABLE + (5 * fooBar)) / fooBar'); // returns `5.6`
parser.parse("(1 + MY_VARIABLE + (5 * fooBar)) / fooBar"); // returns `5.6`
```
### .getVariable(name)
@ -90,9 +93,9 @@ parser.parse('(1 + MY_VARIABLE + (5 * fooBar)) / fooBar'); // returns `5.6`
Get variable name.
```js
parser.setVariable('fooBar', 10);
parser.setVariable("fooBar", 10);
parser.getVariable('fooBar'); // returns `10`
parser.getVariable("fooBar"); // returns `10`
```
### .setFunction(name, fn)
@ -100,17 +103,17 @@ parser.getVariable('fooBar'); // returns `10`
Set custom function which can be visible while parsing formula expression.
```js
parser.setFunction('ADD_5', function(params) {
parser.setFunction("ADD_5", function (params) {
return params[0] + 5;
});
parser.setFunction('GET_LETTER', function(params) {
parser.setFunction("GET_LETTER", function (params) {
var string = params[0];
var index = params[1] - 1;
return string.charAt(index);
});
parser.parse('SUM(4, ADD_5(1))'); // returns `10`
parser.parse("SUM(4, ADD_5(1))"); // returns `10`
parser.parse('GET_LETTER("Some string", 3)'); // returns `m`
```
@ -119,11 +122,11 @@ parser.parse('GET_LETTER("Some string", 3)'); // returns `m`
Get custom function.
```js
parser.setFunction('ADD_5', function(params) {
parser.setFunction("ADD_5", function (params) {
return params[0] + 5;
});
parser.getFunction('ADD_5')([1]); // returns `6`
parser.getFunction("ADD_5")([1]); // returns `6`
```
### .SUPPORTED_FORMULAS
@ -131,7 +134,7 @@ parser.getFunction('ADD_5')([1]); // returns `6`
List of all supported formulas function.
```js
require('hot-formula-parser').SUPPORTED_FORMULAS; // An array of formula names
require("hot-formula-parser").SUPPORTED_FORMULAS; // An array of formula names
```
## API (hooks)
@ -141,13 +144,13 @@ require('hot-formula-parser').SUPPORTED_FORMULAS; // An array of formula names
Fired while retrieving variable. If variable was defined earlier using `setVariable` you can overwrite it by this hook.
```js
parser.on('callVariable', function(name, done) {
if (name === 'foo') {
parser.on("callVariable", function (name, done) {
if (name === "foo") {
done(Math.PI / 2);
}
});
parser.parse('SUM(SIN(foo), COS(foo))'); // returns `1`
parser.parse("SUM(SIN(foo), COS(foo))"); // returns `1`
```
### 'callFunction' (name, params, done)
@ -156,13 +159,13 @@ Fired while calling function. If function was defined earlier using `setFunction
You can also use this to override result of build-in formulas.
```js
parser.on('callFunction', function(name, params, done) {
if (name === 'ADD_5') {
parser.on("callFunction", function (name, params, done) {
if (name === "ADD_5") {
done(params[0] + 5);
}
});
parser.parse('ADD_5(3)'); // returns `8`
parser.parse("ADD_5(3)"); // returns `8`
```
### 'callCellValue' (cellCoord, done)
@ -170,24 +173,29 @@ parser.parse('ADD_5(3)'); // returns `8`
Fired while retrieving cell value by its label (eq: `B3`, `B$3`, `B$3`, `$B$3`).
```js
parser.on('callCellValue', function(cellCoord, done) {
parser.on("callCellValue", function (cellCoord, done) {
// using label
if (cellCoord.label === 'B$6') {
done('hello');
if (cellCoord.label === "B$6") {
done("hello");
}
// or using indexes
if (cellCoord.row.index === 5 && cellCoord.row.isAbsolute && cellCoord.column.index === 1 && !cellCoord.column.isAbsolute) {
done('hello');
if (
cellCoord.row.index === 5 &&
cellCoord.row.isAbsolute &&
cellCoord.column.index === 1 &&
!cellCoord.column.isAbsolute
) {
done("hello");
}
if (cellCoord.label === 'C6') {
if (cellCoord.label === "C6") {
done(0.75);
}
});
parser.parse('B$6'); // returns `"hello"`
parser.parse("B$6"); // returns `"hello"`
parser.parse('B$6&" world"'); // returns `"hello world"`
parser.parse('FISHER(C6)'); // returns `0.9729550745276566`
parser.parse("FISHER(C6)"); // returns `0.9729550745276566`
```
### 'callRangeValue' (startCellCoord, endCellCoord, done)
@ -195,7 +203,7 @@ parser.parse('FISHER(C6)'); // returns `0.9729550745276566`
Fired while retrieving cells range value (eq: `A1:B3`, `$A1:B$3`, `A$1:B$3`, `$A$1:$B$3`).
```js
parser.on('callRangeValue', function(startCellCoord, endCellCoord, done) {
parser.on("callRangeValue", function (startCellCoord, endCellCoord, done) {
var data = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
@ -204,11 +212,19 @@ parser.on('callRangeValue', function(startCellCoord, endCellCoord, done) {
];
var fragment = [];
for (var row = startCellCoord.row.index; row <= endCellCoord.row.index; row++) {
for (
var row = startCellCoord.row.index;
row <= endCellCoord.row.index;
row++
) {
var rowData = data[row];
var colFragment = [];
for (var col = startCellCoord.column.index; col <= endCellCoord.column.index; col++) {
for (
var col = startCellCoord.column.index;
col <= endCellCoord.column.index;
col++
) {
colFragment.push(rowData[col]);
}
fragment.push(colFragment);
@ -219,10 +235,10 @@ parser.on('callRangeValue', function(startCellCoord, endCellCoord, done) {
}
});
parser.parse('JOIN(A1:E2)'); // returns `"1,2,3,4,5,6,7,8,9,10"`
parser.parse('COLUMNS(A1:E2)'); // returns `5`
parser.parse('ROWS(A1:E2)'); // returns `2`
parser.parse('COUNT(A1:E2)'); // returns `10`
parser.parse("JOIN(A1:E2)"); // returns `"1,2,3,4,5,6,7,8,9,10"`
parser.parse("COLUMNS(A1:E2)"); // returns `5`
parser.parse("ROWS(A1:E2)"); // returns `2`
parser.parse("COUNT(A1:E2)"); // returns `10`
parser.parse('COUNTIF(A1:E2, ">5")'); // returns `5`
```
@ -241,6 +257,5 @@ The MIT License (see the [LICENSE](https://github.com/handsontable/formula-parse
### Contact
You can contact us at hello@handsontable.com.
</details>
</details>

View File

@ -7,9 +7,7 @@
"type": "git",
"url": "https://github.com/handsontable/formula-parser.git"
},
"authors": [
"Handsoncode", "Handsoncode <hello@handsontable.com>"
],
"authors": ["Handsoncode", "Handsoncode <hello@handsontable.com>"],
"keywords": [
"formula",
"formulas",
@ -18,10 +16,5 @@
"excel",
"spreadsheet"
],
"ignore": [
"**/.*",
"node_modules",
"src",
"test"
]
"ignore": ["**/.*", "node_modules", "src", "test"]
}

View File

@ -1,19 +1,20 @@
const fse = require('fs-extra');
const path = require('path');
const fse = require("fs-extra");
const path = require("path");
const TARGET_PATH = './tmp';
const TARGET_PATH = "./tmp";
const filesToMove = [
'dist',
'CHANGELOG.md',
'CONTRIBUTING.md',
'LICENSE',
'package.json',
'README.md',
"dist",
"CHANGELOG.md",
"CONTRIBUTING.md",
"LICENSE",
"package.json",
"README.md",
];
filesToMove.forEach((file) => {
fse.copySync(
path.resolve(`./${file}`),
path.resolve(`${TARGET_PATH}/${file}`),
{ overwrite: true });
{ overwrite: true }
);
});

View File

@ -1,21 +1,21 @@
export const ERROR = 'ERROR';
export const ERROR_DIV_ZERO = 'DIV/0';
export const ERROR_NAME = 'NAME';
export const ERROR_NOT_AVAILABLE = 'N/A';
export const ERROR_NULL = 'NULL';
export const ERROR_NUM = 'NUM';
export const ERROR_REF = 'REF';
export const ERROR_VALUE = 'VALUE';
export const ERROR = "ERROR";
export const ERROR_DIV_ZERO = "DIV/0";
export const ERROR_NAME = "NAME";
export const ERROR_NOT_AVAILABLE = "N/A";
export const ERROR_NULL = "NULL";
export const ERROR_NUM = "NUM";
export const ERROR_REF = "REF";
export const ERROR_VALUE = "VALUE";
const errors = {
[ERROR]: '#ERROR!',
[ERROR_DIV_ZERO]: '#DIV/0!',
[ERROR_NAME]: '#NAME?',
[ERROR_NOT_AVAILABLE]: '#N/A',
[ERROR_NULL]: '#NULL!',
[ERROR_NUM]: '#NUM!',
[ERROR_REF]: '#REF!',
[ERROR_VALUE]: '#VALUE!',
[ERROR]: "#ERROR!",
[ERROR_DIV_ZERO]: "#DIV/0!",
[ERROR_NAME]: "#NAME?",
[ERROR_NOT_AVAILABLE]: "#N/A",
[ERROR_NULL]: "#NULL!",
[ERROR_NUM]: "#NUM!",
[ERROR_REF]: "#REF!",
[ERROR_VALUE]: "#VALUE!",
};
/**
@ -27,7 +27,7 @@ const errors = {
export default function error(type) {
let result;
type = (type + '').replace(/#|!|\?/g, '');
type = (type + "").replace(/#|!|\?/g, "");
if (errors[type]) {
result = errors[type];

View File

@ -1,18 +1,18 @@
/* eslint-disable import/no-named-as-default-member */
import add from './operator/add';
import ampersand from './operator/ampersand';
import divide from './operator/divide';
import equal from './operator/equal';
import formulaFunction from './operator/formula-function';
import greaterThan from './operator/greater-than';
import greaterThanOrEqual from './operator/greater-than-or-equal';
import lessThan from './operator/less-than';
import lessThanOrEqual from './operator/less-than-or-equal';
import minus from './operator/minus';
import multiply from './operator/multiply';
import notEqual from './operator/not-equal';
import power from './operator/power';
import {ERROR_NAME} from './../error';
import add from "./operator/add";
import ampersand from "./operator/ampersand";
import divide from "./operator/divide";
import equal from "./operator/equal";
import formulaFunction from "./operator/formula-function";
import greaterThan from "./operator/greater-than";
import greaterThanOrEqual from "./operator/greater-than-or-equal";
import lessThan from "./operator/less-than";
import lessThanOrEqual from "./operator/less-than-or-equal";
import minus from "./operator/minus";
import multiply from "./operator/multiply";
import notEqual from "./operator/not-equal";
import power from "./operator/power";
import { ERROR_NAME } from "./../error";
const availableOperators = Object.create(null);

View File

@ -1,10 +1,13 @@
import {toNumber} from './../../helper/number';
import {ERROR_VALUE} from './../../error';
import { toNumber } from "./../../helper/number";
import { ERROR_VALUE } from "./../../error";
export const SYMBOL = '+';
export const SYMBOL = "+";
export default function func(first, ...rest) {
const result = rest.reduce((acc, value) => acc + toNumber(value || 0), toNumber(first || 0));
const result = rest.reduce(
(acc, value) => acc + toNumber(value || 0),
toNumber(first || 0)
);
if (isNaN(result)) {
throw Error(ERROR_VALUE);

View File

@ -1,7 +1,7 @@
export const SYMBOL = '&';
export const SYMBOL = "&";
export default function func(...params) {
return params.reduce((acc, value) => acc + value.toString(), '');
return params.reduce((acc, value) => acc + value.toString(), "");
}
func.SYMBOL = SYMBOL;

View File

@ -1,10 +1,13 @@
import {toNumber} from './../../helper/number';
import {ERROR_DIV_ZERO, ERROR_VALUE} from './../../error';
import { toNumber } from "./../../helper/number";
import { ERROR_DIV_ZERO, ERROR_VALUE } from "./../../error";
export const SYMBOL = '/';
export const SYMBOL = "/";
export default function func(first, ...rest) {
const result = rest.reduce((acc, value) => acc / toNumber(value), toNumber(first));
const result = rest.reduce(
(acc, value) => acc / toNumber(value),
toNumber(first)
);
if (result === Infinity) {
return ERROR_DIV_ZERO;

View File

@ -1,4 +1,4 @@
export const SYMBOL = '=';
export const SYMBOL = "=";
export default function func(exp1, exp2) {
return exp1 === exp2;

View File

@ -1,6 +1,6 @@
import * as formulajs from '@formulajs/formulajs';
import SUPPORTED_FORMULAS from './../../supported-formulas';
import {ERROR_NAME} from './../../error';
import * as formulajs from "@formulajs/formulajs";
import SUPPORTED_FORMULAS from "./../../supported-formulas";
import { ERROR_NAME } from "./../../error";
export const SYMBOL = SUPPORTED_FORMULAS;
@ -8,7 +8,7 @@ export default function func(symbol) {
return function __formulaFunction(...params) {
symbol = symbol.toUpperCase();
const symbolParts = symbol.split('.');
const symbolParts = symbol.split(".");
let foundFormula = false;
let result;

View File

@ -1,4 +1,4 @@
export const SYMBOL = '>=';
export const SYMBOL = ">=";
export default function func(exp1, exp2) {
return exp1 >= exp2;

View File

@ -1,4 +1,4 @@
export const SYMBOL = '>';
export const SYMBOL = ">";
export default function func(exp1, exp2) {
return exp1 > exp2;

View File

@ -1,4 +1,4 @@
export const SYMBOL = '<=';
export const SYMBOL = "<=";
export default function func(exp1, exp2) {
return exp1 <= exp2;

View File

@ -1,4 +1,4 @@
export const SYMBOL = '<';
export const SYMBOL = "<";
export default function func(exp1, exp2) {
return exp1 < exp2;

View File

@ -1,10 +1,13 @@
import {toNumber} from './../../helper/number';
import {ERROR_VALUE} from './../../error';
import { toNumber } from "./../../helper/number";
import { ERROR_VALUE } from "./../../error";
export const SYMBOL = '-';
export const SYMBOL = "-";
export default function func(first, ...rest) {
const result = rest.reduce((acc, value) => acc - toNumber(value), toNumber(first));
const result = rest.reduce(
(acc, value) => acc - toNumber(value),
toNumber(first)
);
if (isNaN(result)) {
throw Error(ERROR_VALUE);

View File

@ -1,10 +1,13 @@
import {toNumber} from './../../helper/number';
import {ERROR_VALUE} from './../../error';
import { toNumber } from "./../../helper/number";
import { ERROR_VALUE } from "./../../error";
export const SYMBOL = '*';
export const SYMBOL = "*";
export default function func(first, ...rest) {
const result = rest.reduce((acc, value) => acc * toNumber(value), toNumber(first));
const result = rest.reduce(
(acc, value) => acc * toNumber(value),
toNumber(first)
);
if (isNaN(result)) {
throw Error(ERROR_VALUE);

View File

@ -1,4 +1,4 @@
export const SYMBOL = '<>';
export const SYMBOL = "<>";
export default function func(exp1, exp2) {
return exp1 !== exp2;

View File

@ -1,7 +1,7 @@
import {toNumber} from './../../helper/number';
import {ERROR_VALUE} from './../../error';
import { toNumber } from "./../../helper/number";
import { ERROR_VALUE } from "./../../error";
export const SYMBOL = '^';
export const SYMBOL = "^";
export default function func(exp1, exp2) {
const result = Math.pow(toNumber(exp1), toNumber(exp2));

View File

@ -23,7 +23,7 @@ export function rowLabelToIndex(label) {
* @returns {String} Returns row label (eq. '1', '7').
*/
export function rowIndexToLabel(row) {
let result = '';
let result = "";
if (row >= 0) {
result = `${row + 1}`;
@ -32,7 +32,7 @@ export function rowIndexToLabel(row) {
return result;
}
const COLUMN_LABEL_BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const COLUMN_LABEL_BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const COLUMN_LABEL_BASE_LENGTH = COLUMN_LABEL_BASE.length;
/**
@ -44,11 +44,13 @@ const COLUMN_LABEL_BASE_LENGTH = COLUMN_LABEL_BASE.length;
export function columnLabelToIndex(label) {
let result = 0;
if (typeof label === 'string') {
if (typeof label === "string") {
label = label.toUpperCase();
for (let i = 0, j = label.length - 1; i < label.length; i += 1, j -= 1) {
result += Math.pow(COLUMN_LABEL_BASE_LENGTH, j) * (COLUMN_LABEL_BASE.indexOf(label[i]) + 1);
result +=
Math.pow(COLUMN_LABEL_BASE_LENGTH, j) *
(COLUMN_LABEL_BASE.indexOf(label[i]) + 1);
}
}
--result;
@ -63,20 +65,23 @@ export function columnLabelToIndex(label) {
* @returns {String} Returns column label (eq. 'ABB', 'CNQ').
*/
export function columnIndexToLabel(column) {
let result = '';
let result = "";
while (column >= 0) {
result = String.fromCharCode((column % COLUMN_LABEL_BASE_LENGTH) + 97) + result;
result =
String.fromCharCode((column % COLUMN_LABEL_BASE_LENGTH) + 97) + result;
column = Math.floor(column / COLUMN_LABEL_BASE_LENGTH) - 1;
}
return result.toUpperCase();
}
const simpleSheetName = '[A-Za-z0-9_\u00C0-\u02AF]+';
const simpleSheetName = "[A-Za-z0-9_\u00C0-\u02AF]+";
const quotedSheetName = "'(?:(?!').|'')*'";
const sheetNameRegexp = `(${simpleSheetName}|${quotedSheetName})!`;
const LABEL_EXTRACT_REGEXP = new RegExp(`^(?:${sheetNameRegexp})?([$])?([A-Za-z]*)([$])?([0-9]*)$`);
const LABEL_EXTRACT_REGEXP = new RegExp(
`^(?:${sheetNameRegexp})?([$])?([A-Za-z]*)([$])?([0-9]*)$`
);
/**
* Extract cell coordinates.
@ -85,23 +90,31 @@ const LABEL_EXTRACT_REGEXP = new RegExp(`^(?:${sheetNameRegexp})?([$])?([A-Za-z]
* @returns {Array} Returns an array of objects.
*/
export function extractLabel(label) {
if (typeof label !== 'string' || !LABEL_EXTRACT_REGEXP.test(label)) {
if (typeof label !== "string" || !LABEL_EXTRACT_REGEXP.test(label)) {
return [];
}
const [, sheetNameStr, columnAbs, column, rowAbs, row] = label.toUpperCase().match(LABEL_EXTRACT_REGEXP);
const [, sheetNameStr, columnAbs, column, rowAbs, row] = label
.toUpperCase()
.match(LABEL_EXTRACT_REGEXP);
if (column == null && row == null) return [];
const sheetName = sheetNameStr == null ? null : label.slice(0, sheetNameStr.length).replace(/^'|'$/g, "").replace(/''/g, "'");
const sheetName =
sheetNameStr == null
? null
: label
.slice(0, sheetNameStr.length)
.replace(/^'|'$/g, "")
.replace(/''/g, "'");
return [
{
index: rowLabelToIndex(row),
label: row,
isAbsolute: rowAbs === '$',
isAbsolute: rowAbs === "$",
},
{
index: columnLabelToIndex(column),
label: column,
isAbsolute: columnAbs === '$',
isAbsolute: columnAbs === "$",
},
sheetName,
];
@ -115,8 +128,9 @@ export function extractLabel(label) {
* @returns {String} Returns cell label.
*/
export function toLabel(row, column) {
const rowLabel = (row.isAbsolute ? '$' : '') + rowIndexToLabel(row.index);
const columnLabel = (column.isAbsolute ? '$' : '') + columnIndexToLabel(column.index);
const rowLabel = (row.isAbsolute ? "$" : "") + rowIndexToLabel(row.index);
const columnLabel =
(column.isAbsolute ? "$" : "") + columnIndexToLabel(column.index);
return columnLabel + rowLabel;
}

View File

@ -7,11 +7,11 @@
export function toNumber(number) {
let result;
if (typeof number === 'number') {
if (typeof number === "number") {
result = number;
} else if (typeof number === 'string') {
result = number.indexOf('.') > -1 ? parseFloat(number) : parseInt(number, 10);
} else if (typeof number === "string") {
result =
number.indexOf(".") > -1 ? parseFloat(number) : parseInt(number, 10);
}
return result;

View File

@ -1,5 +1,5 @@
import Parser from './parser';
import SUPPORTED_FORMULAS from './supported-formulas';
import Parser from "./parser";
import SUPPORTED_FORMULAS from "./supported-formulas";
import error, {
ERROR,
ERROR_DIV_ZERO,
@ -9,7 +9,7 @@ import error, {
ERROR_NUM,
ERROR_REF,
ERROR_VALUE,
} from './error';
} from "./error";
import {
extractLabel,
toLabel,
@ -17,7 +17,7 @@ import {
columnLabelToIndex,
rowIndexToLabel,
rowLabelToIndex,
} from './helper/cell';
} from "./helper/cell";
export {
SUPPORTED_FORMULAS,

View File

@ -1,10 +1,15 @@
import Emitter from 'tiny-emitter';
import evaluateByOperator from './evaluate-by-operator/evaluate-by-operator';
import {Parser as GrammarParser} from './grammar-parser/grammar-parser';
import {trimEdges} from './helper/string';
import {toNumber, invertNumber} from './helper/number';
import errorParser, {isValidStrict as isErrorValid, ERROR, ERROR_NAME, ERROR_VALUE} from './error';
import {extractLabel, toLabel} from './helper/cell';
import Emitter from "tiny-emitter";
import evaluateByOperator from "./evaluate-by-operator/evaluate-by-operator";
import { Parser as GrammarParser } from "./grammar-parser/grammar-parser";
import { trimEdges } from "./helper/string";
import { toNumber, invertNumber } from "./helper/number";
import errorParser, {
isValidStrict as isErrorValid,
ERROR,
ERROR_NAME,
ERROR_VALUE,
} from "./error";
import { extractLabel, toLabel } from "./helper/cell";
/**
* @class Parser
@ -28,10 +33,9 @@ class Parser extends Emitter {
this.functions = Object.create(null);
this.options = Object.create(null);
this
.setVariable('TRUE', true)
.setVariable('FALSE', false)
.setVariable('NULL', null);
this.setVariable("TRUE", true)
.setVariable("FALSE", false)
.setVariable("NULL", null);
}
/**
@ -48,8 +52,8 @@ class Parser extends Emitter {
this.options = options;
try {
if (expression === '') {
result = '';
if (expression === "") {
result = "";
} else {
result = this.parser.parse(expression);
}
@ -107,7 +111,7 @@ class Parser extends Emitter {
_callVariable(name) {
let value = this.getVariable(name);
this.emit('callVariable', name, (newValue) => {
this.emit("callVariable", name, (newValue) => {
if (newValue !== void 0) {
value = newValue;
}
@ -159,7 +163,7 @@ class Parser extends Emitter {
value = fn(params);
}
this.emit('callFunction', name, params, (newValue) => {
this.emit("callFunction", name, params, (newValue) => {
if (newValue !== void 0) {
value = newValue;
}
@ -184,12 +188,17 @@ class Parser extends Emitter {
return row.index + 1;
} else if (row?.index === -1) {
throw Error(ERROR_NAME);
}
}
let value = void 0;
this.emit('callCellValue', {label, row, column, sheetName}, this.options, (_value) => {
value = _value;
});
this.emit(
"callCellValue",
{ label, row, column, sheetName },
this.options,
(_value) => {
value = _value;
}
);
return value;
}
@ -233,9 +242,15 @@ class Parser extends Emitter {
let value = [];
this.emit('callRangeValue', startCell, endCell, this.options, (_value = []) => {
value = _value;
});
this.emit(
"callRangeValue",
startCell,
endCell,
this.options,
(_value = []) => {
value = _value;
}
);
return value;
}

View File

@ -1,4 +1,4 @@
import * as formulajs from '@formulajs/formulajs';
import * as formulajs from "@formulajs/formulajs";
const SUPPORTED_FORMULAS = Object.keys(formulajs);

View File

@ -20,10 +20,12 @@ jest.addMatchers({
if (a === e || isNaN(a) === isNaN(e)) {
pass = true;
} else if (typeof a === 'number' && typeof e === 'number' && Math.abs(a - e) < tolerance(precision)) {
} else if (
typeof a === "number" &&
typeof e === "number" &&
Math.abs(a - e) < tolerance(precision)
) {
pass = true;
} else {
pass = false;
}

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() coordinates', () => {
describe(".parse() coordinates", () => {
let parser;
let cellCoord;
let startCellCoord;
@ -9,11 +9,11 @@ describe('.parse() coordinates', () => {
beforeEach(() => {
parser = new Parser();
parser.on('callCellValue', (_cellCoord, done) => {
parser.on("callCellValue", (_cellCoord, done) => {
cellCoord = _cellCoord;
done(55);
});
parser.on('callRangeValue', (_startCellCoord, _endCellCoord, done) => {
parser.on("callRangeValue", (_startCellCoord, _endCellCoord, done) => {
startCellCoord = _startCellCoord;
endCellCoord = _endCellCoord;
done([[3, 6, 10]]);
@ -26,275 +26,368 @@ describe('.parse() coordinates', () => {
endCellCoord = null;
});
it('should parse relative cell', () => {
expect(parser.parse('A1')).toMatchObject({error: null, result: 55});
it("should parse relative cell", () => {
expect(parser.parse("A1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(parser.parse('a1')).toMatchObject({error: null, result: 55});
expect(parser.parse("a1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
});
it('should parse absolute cell', () => {
expect(parser.parse('$A$1')).toMatchObject({error: null, result: 55});
it("should parse absolute cell", () => {
expect(parser.parse("$A$1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(parser.parse('$a$1')).toMatchObject({error: null, result: 55});
expect(parser.parse("$a$1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(parser.parse('$A$$$$1')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('$$A$1')).toMatchObject({error: '#ERROR!', result: null});
});
it('should parse mixed cell', () => {
expect(parser.parse('$A1')).toMatchObject({error: null, result: 55});
expect(cellCoord).toMatchObject({
label: '$A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
expect(parser.parse("$A$$$$1")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse('A$1')).toMatchObject({error: null, result: 55});
expect(cellCoord).toMatchObject({
label: 'A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
});
expect(parser.parse('a$1')).toMatchObject({error: null, result: 55});
expect(cellCoord).toMatchObject({
label: 'A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
});
expect(parser.parse('A$$1')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('$$A1')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('A1$')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('A1$$$')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('a1$$$')).toMatchObject({error: '#ERROR!', result: null});
});
it('should parse relative cells range', () => {
expect(parser.parse('A1:B2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
});
expect(parser.parse('a1:B2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
});
expect(parser.parse('A1:b2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
});
expect(parser.parse('a1:b2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
expect(parser.parse("$$A$1")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse absolute cells range', () => {
expect(parser.parse('$A$1:$B$2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: '$B$2',
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
it("should parse mixed cell", () => {
expect(parser.parse("$A1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: "$A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(parser.parse('$a$1:$B$2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: '$B$2',
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
expect(parser.parse("A$1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: "A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(parser.parse('$a$1:$b$2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(startCellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
});
expect(endCellCoord).toMatchObject({
label: '$B$2',
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
expect(parser.parse("a$1")).toMatchObject({ error: null, result: 55 });
expect(cellCoord).toMatchObject({
label: "A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(parser.parse('$A$$1:$B$2')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('$A$1:$B$$2')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('$A$1:$$B$2')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('$$A$1:$B$2')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse("A$$1")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("$$A1")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("A1$")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("A1$$$")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("a1$$$")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse mixed cells range', () => {
expect(parser.parse('$A$1:B2')).toMatchObject({error: null, result: [[3, 6, 10]]});
it("should parse relative cells range", () => {
expect(parser.parse("A1:B2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse('$A$1:b2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("a1:B2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse('A1:$B$2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("A1:b2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: '$B$2',
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse('$A$1:B$2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("a1:b2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: '$A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: true, label: 'A'},
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: 'B$2',
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
});
expect(parser.parse('A1:$B2')).toMatchObject({error: null, result: [[3, 6, 10]]});
it("should parse absolute cells range", () => {
expect(parser.parse("$A$1:$B$2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: 'A1',
row: {index: 0, isAbsolute: false, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: '$B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
label: "$B$2",
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse('A$1:B2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("$a$1:$B$2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: 'A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: 'B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: false, label: 'B'},
label: "$B$2",
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse('A$1:$B$2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("$a$1:$b$2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: 'A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: '$B$2',
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
label: "$B$2",
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse('A$1:$B2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("$A$$1:$B$2")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("$A$1:$B$$2")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("$A$1:$$B$2")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("$$A$1:$B$2")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it("should parse mixed cells range", () => {
expect(parser.parse("$A$1:B2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: 'A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: '$B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse('a$1:$b2')).toMatchObject({error: null, result: [[3, 6, 10]]});
expect(parser.parse("$A$1:b2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: 'A$1',
row: {index: 0, isAbsolute: true, label: '1'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: '$B2',
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 1, isAbsolute: true, label: 'B'},
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse('A1:$$B2')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('A1:B2$')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('a1:b2$')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('A1$:B2')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse("A1:$B$2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "$B$2",
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse("$A$1:B$2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "$A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: true, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "B$2",
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse("A1:$B2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "A1",
row: { index: 0, isAbsolute: false, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "$B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse("A$1:B2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: false, label: "B" },
});
expect(parser.parse("A$1:$B$2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "$B$2",
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse("A$1:$B2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "$B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse("a$1:$b2")).toMatchObject({
error: null,
result: [[3, 6, 10]],
});
expect(startCellCoord).toMatchObject({
label: "A$1",
row: { index: 0, isAbsolute: true, label: "1" },
column: { index: 0, isAbsolute: false, label: "A" },
});
expect(endCellCoord).toMatchObject({
label: "$B2",
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 1, isAbsolute: true, label: "B" },
});
expect(parser.parse("A1:$$B2")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("A1:B2$")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("a1:b2$")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("A1$:B2")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() error', () => {
describe(".parse() error", () => {
let parser;
beforeEach(() => {
@ -10,54 +10,129 @@ describe('.parse() error', () => {
parser = null;
});
it('should parse general error', () => {
expect(parser.parse('#ERROR!')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#ERRfefweOR!')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse(' #ERRfefweOR! ')).toMatchObject({error: '#ERROR!', result: null});
it("should parse general error", () => {
expect(parser.parse("#ERROR!")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#ERRfefweOR!")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse(" #ERRfefweOR! ")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse DIV/0 error', () => {
expect(parser.parse('#DIV/0!')).toMatchObject({error: '#DIV/0!', result: null});
expect(parser.parse('#DIV/0?')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#DIV/1!')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#DIV/')).toMatchObject({error: '#ERROR!', result: null});
it("should parse DIV/0 error", () => {
expect(parser.parse("#DIV/0!")).toMatchObject({
error: "#DIV/0!",
result: null,
});
expect(parser.parse("#DIV/0?")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#DIV/1!")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#DIV/")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse NAME error', () => {
expect(parser.parse('#NAME?')).toMatchObject({error: '#NAME?', result: null});
expect(parser.parse('#NAME!')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#NAMe!')).toMatchObject({error: '#ERROR!', result: null});
it("should parse NAME error", () => {
expect(parser.parse("#NAME?")).toMatchObject({
error: "#NAME?",
result: null,
});
expect(parser.parse("#NAME!")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#NAMe!")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse N/A error', () => {
expect(parser.parse('#N/A')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('#N/A!')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#N/A?')).toMatchObject({error: '#ERROR!', result: null});
it("should parse N/A error", () => {
expect(parser.parse("#N/A")).toMatchObject({ error: "#N/A", result: null });
expect(parser.parse("#N/A!")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#N/A?")).toMatchObject({
error: "#ERROR!",
result: null,
});
/* eslint-disable no-useless-escape */
expect(parser.parse('#N\A')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse("#NA")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse NULL error', () => {
expect(parser.parse('#NULL!')).toMatchObject({error: '#NULL!', result: null});
expect(parser.parse('#NULL?')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#NULl!')).toMatchObject({error: '#ERROR!', result: null});
it("should parse NULL error", () => {
expect(parser.parse("#NULL!")).toMatchObject({
error: "#NULL!",
result: null,
});
expect(parser.parse("#NULL?")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#NULl!")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse NUM error', () => {
expect(parser.parse('#NUM!')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('#NUM?')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#NuM!')).toMatchObject({error: '#ERROR!', result: null});
it("should parse NUM error", () => {
expect(parser.parse("#NUM!")).toMatchObject({
error: "#NUM!",
result: null,
});
expect(parser.parse("#NUM?")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#NuM!")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse REF error', () => {
expect(parser.parse('#REF!')).toMatchObject({error: '#REF!', result: null});
expect(parser.parse('#REF?')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#REf!')).toMatchObject({error: '#ERROR!', result: null});
it("should parse REF error", () => {
expect(parser.parse("#REF!")).toMatchObject({
error: "#REF!",
result: null,
});
expect(parser.parse("#REF?")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#REf!")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should parse VALUE error', () => {
expect(parser.parse('#VALUE!')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('#VALUE?')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('#VALUe!')).toMatchObject({error: '#ERROR!', result: null});
it("should parse VALUE error", () => {
expect(parser.parse("#VALUE!")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("#VALUE?")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("#VALUe!")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse()', () => {
describe(".parse()", () => {
let parser;
beforeEach(() => {
@ -10,20 +10,32 @@ describe('.parse()', () => {
parser = null;
});
it('should return error when number of arguments is not valid', () => {
it("should return error when number of arguments is not valid", () => {
/* eslint-disable */
expect(parser.parse('ACOTH("foo")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse("ACOTH('foo')")).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ACOTH("foo")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("ACOTH('foo')")).toMatchObject({
error: "#VALUE!",
result: null,
});
/* eslint-enable */
});
it('should return error when used variable is not defined', () => {
expect(parser.parse('ACOTH(foo)')).toMatchObject({error: '#NAME?', result: null});
it("should return error when used variable is not defined", () => {
expect(parser.parse("ACOTH(foo)")).toMatchObject({
error: "#NAME?",
result: null,
});
});
it('should evaluate formula expression provided in lower case', () => {
parser.setVariable('foo', [7, 3.5, 3.5, 1, 2]);
it("should evaluate formula expression provided in lower case", () => {
parser.setVariable("foo", [7, 3.5, 3.5, 1, 2]);
expect(parser.parse('sum(2, 3, Rank.eq(2, foo))')).toMatchObject({error: null, result: 9});
expect(parser.parse("sum(2, 3, Rank.eq(2, foo))")).toMatchObject({
error: null,
result: 9,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() date & time formulas', () => {
describe(".parse() date & time formulas", () => {
let parser;
beforeEach(() => {
@ -10,10 +10,13 @@ describe('.parse() date & time formulas', () => {
parser = null;
});
it('DATE', () => {
expect(parser.parse('DATE()')).toMatchObject({error: '#VALUE!', result: null});
it("DATE", () => {
expect(parser.parse("DATE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
const {error, result} = parser.parse('DATE(2001, 5, 12)');
const { error, result } = parser.parse("DATE(2001, 5, 12)");
expect(error).toBeNull();
expect(result.getFullYear()).toBe(2001);
@ -21,151 +24,345 @@ describe('.parse() date & time formulas', () => {
expect(result.getDate()).toBe(12);
});
it('DATEVALUE', () => {
expect(parser.parse('DATEVALUE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DATEVALUE("1/1/1900")')).toMatchObject({error: null, result: 1});
expect(parser.parse('DATEVALUE("1/1/2000")')).toMatchObject({error: null, result: 36526});
it("DATEVALUE", () => {
expect(parser.parse("DATEVALUE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('DATEVALUE("1/1/1900")')).toMatchObject({
error: null,
result: 1,
});
expect(parser.parse('DATEVALUE("1/1/2000")')).toMatchObject({
error: null,
result: 36526,
});
});
it('DAY', () => {
expect(parser.parse('DAY()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DAY(1)')).toMatchObject({error: null, result: 1});
expect(parser.parse('DAY(2958465)')).toMatchObject({error: null, result: 31});
expect(parser.parse('DAY("2958465")')).toMatchObject({error: null, result: 31});
it("DAY", () => {
expect(parser.parse("DAY()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DAY(1)")).toMatchObject({ error: null, result: 1 });
expect(parser.parse("DAY(2958465)")).toMatchObject({
error: null,
result: 31,
});
expect(parser.parse('DAY("2958465")')).toMatchObject({
error: null,
result: 31,
});
});
it('DAYS', () => {
expect(parser.parse('DAYS()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DAYS(1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DAYS(1, 6)')).toMatchObject({error: null, result: -5});
expect(parser.parse('DAYS("1/2/2000", "1/10/2001")')).toMatchObject({error: null, result: -374});
it("DAYS", () => {
expect(parser.parse("DAYS()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DAYS(1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DAYS(1, 6)")).toMatchObject({
error: null,
result: -5,
});
expect(parser.parse('DAYS("1/2/2000", "1/10/2001")')).toMatchObject({
error: null,
result: -374,
});
});
it('DAYS360', () => {
expect(parser.parse('DAYS360()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DAYS360(1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DAYS360(1, 6)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DAYS360("1/1/1901", "2/1/1901", TRUE)')).toMatchObject({error: null, result: 30});
expect(parser.parse('DAYS360("1/1/1901", "12/31/1901", FALSE)')).toMatchObject({error: null, result: 360});
it("DAYS360", () => {
expect(parser.parse("DAYS360()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DAYS360(1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DAYS360(1, 6)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('DAYS360("1/1/1901", "2/1/1901", TRUE)')).toMatchObject(
{ error: null, result: 30 }
);
expect(
parser.parse('DAYS360("1/1/1901", "12/31/1901", FALSE)')
).toMatchObject({ error: null, result: 360 });
});
it('EDATE', () => {
expect(parser.parse('EDATE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('EDATE(1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('EDATE("1/1/1900", 1)')).toMatchObject({error: null, result: 32});
it("EDATE", () => {
expect(parser.parse("EDATE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("EDATE(1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('EDATE("1/1/1900", 1)')).toMatchObject({
error: null,
result: 32,
});
});
it('EOMONTH', () => {
expect(parser.parse('EOMONTH()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('EOMONTH(1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('EOMONTH("1/1/1900", 1)')).toMatchObject({error: null, result: 59});
it("EOMONTH", () => {
expect(parser.parse("EOMONTH()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("EOMONTH(1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('EOMONTH("1/1/1900", 1)')).toMatchObject({
error: null,
result: 59,
});
});
it('HOUR', () => {
expect(parser.parse('HOUR()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('HOUR("1/1/1900 16:33")')).toMatchObject({error: null, result: 16});
it("HOUR", () => {
expect(parser.parse("HOUR()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('HOUR("1/1/1900 16:33")')).toMatchObject({
error: null,
result: 16,
});
});
it('INTERVAL', () => {
expect(parser.parse('INTERVAL()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('INTERVAL(0)')).toMatchObject({error: null, result: 'PT'});
expect(parser.parse('INTERVAL(1)')).toMatchObject({error: null, result: 'PT1S'});
expect(parser.parse('INTERVAL(60)')).toMatchObject({error: null, result: 'PT1M'});
expect(parser.parse('INTERVAL(10000000)')).toMatchObject({error: null, result: 'P3M25DT17H46M40S'});
it("INTERVAL", () => {
expect(parser.parse("INTERVAL()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("INTERVAL(0)")).toMatchObject({
error: null,
result: "PT",
});
expect(parser.parse("INTERVAL(1)")).toMatchObject({
error: null,
result: "PT1S",
});
expect(parser.parse("INTERVAL(60)")).toMatchObject({
error: null,
result: "PT1M",
});
expect(parser.parse("INTERVAL(10000000)")).toMatchObject({
error: null,
result: "P3M25DT17H46M40S",
});
});
it('ISOWEEKNUM', () => {
expect(parser.parse('ISOWEEKNUM()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ISOWEEKNUM("1/8/1901")')).toMatchObject({error: null, result: 2});
expect(parser.parse('ISOWEEKNUM("6/6/1902")')).toMatchObject({error: null, result: 23});
it("ISOWEEKNUM", () => {
expect(parser.parse("ISOWEEKNUM()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('ISOWEEKNUM("1/8/1901")')).toMatchObject({
error: null,
result: 2,
});
expect(parser.parse('ISOWEEKNUM("6/6/1902")')).toMatchObject({
error: null,
result: 23,
});
});
it('MINUTE', () => {
expect(parser.parse('MINUTE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('MINUTE("1/1/1901 1:01")')).toMatchObject({error: null, result: 1});
expect(parser.parse('MINUTE("1/1/1901 15:36")')).toMatchObject({error: null, result: 36});
it("MINUTE", () => {
expect(parser.parse("MINUTE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('MINUTE("1/1/1901 1:01")')).toMatchObject({
error: null,
result: 1,
});
expect(parser.parse('MINUTE("1/1/1901 15:36")')).toMatchObject({
error: null,
result: 36,
});
});
it('MONTH', () => {
expect(parser.parse('MONTH()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('MONTH("2/1/1901")')).toMatchObject({error: null, result: 2});
expect(parser.parse('MONTH("10/1/1901")')).toMatchObject({error: null, result: 10});
it("MONTH", () => {
expect(parser.parse("MONTH()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('MONTH("2/1/1901")')).toMatchObject({
error: null,
result: 2,
});
expect(parser.parse('MONTH("10/1/1901")')).toMatchObject({
error: null,
result: 10,
});
});
it('NETWORKDAYS', () => {
expect(parser.parse('NETWORKDAYS()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NETWORKDAYS("2/1/1901")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NETWORKDAYS("2013-12-04", "2013-12-05")')).toMatchObject({error: null, result: 2});
expect(parser.parse('NETWORKDAYS("2013-11-04", "2013-12-05")')).toMatchObject({error: null, result: 24});
it("NETWORKDAYS", () => {
expect(parser.parse("NETWORKDAYS()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('NETWORKDAYS("2/1/1901")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(
parser.parse('NETWORKDAYS("2013-12-04", "2013-12-05")')
).toMatchObject({ error: null, result: 2 });
expect(
parser.parse('NETWORKDAYS("2013-11-04", "2013-12-05")')
).toMatchObject({ error: null, result: 24 });
});
it('NOW', () => {
const {error, result} = parser.parse('NOW()');
it("NOW", () => {
const { error, result } = parser.parse("NOW()");
const now = new Date();
expect(error).toBeNull();
expect(result.toString()).toBe(now.toString());
});
it('SECOND', () => {
expect(parser.parse('SECOND()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SECOND("2/1/1901 13:33:12")')).toMatchObject({error: null, result: 12});
it("SECOND", () => {
expect(parser.parse("SECOND()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('SECOND("2/1/1901 13:33:12")')).toMatchObject({
error: null,
result: 12,
});
});
it('TIME', () => {
expect(parser.parse('TIME()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TIME(0)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TIME(0, 0)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TIME(0, 0, 0)')).toMatchObject({error: null, result: 0});
expect(parser.parse('TIME(1, 1, 1)')).toMatchObject({error: null, result: 0.04237268518518519});
expect(parser.parse('TIME(24, 0, 0)')).toMatchObject({error: null, result: 1});
it("TIME", () => {
expect(parser.parse("TIME()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("TIME(0)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("TIME(0, 0)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("TIME(0, 0, 0)")).toMatchObject({
error: null,
result: 0,
});
expect(parser.parse("TIME(1, 1, 1)")).toMatchObject({
error: null,
result: 0.04237268518518519,
});
expect(parser.parse("TIME(24, 0, 0)")).toMatchObject({
error: null,
result: 1,
});
});
it('TIMEVALUE', () => {
expect(parser.parse('TIMEVALUE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TIMEVALUE("1/1/1900 00:00:00")')).toMatchObject({error: null, result: 0});
expect(parser.parse('TIMEVALUE("1/1/1900 23:00:00")')).toMatchObject({error: null, result: 0.9583333333333334});
it("TIMEVALUE", () => {
expect(parser.parse("TIMEVALUE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('TIMEVALUE("1/1/1900 00:00:00")')).toMatchObject({
error: null,
result: 0,
});
expect(parser.parse('TIMEVALUE("1/1/1900 23:00:00")')).toMatchObject({
error: null,
result: 0.9583333333333334,
});
});
it('TODAY', () => {
const {error, result} = parser.parse('TODAY()');
it("TODAY", () => {
const { error, result } = parser.parse("TODAY()");
const now = new Date();
expect(error).toBeNull();
expect(result.getDate()).toBe(now.getDate());
});
it('WEEKDAY', () => {
expect(parser.parse('WEEKDAY()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('WEEKDAY("1/1/1901")')).toMatchObject({error: null, result: 3});
expect(parser.parse('WEEKDAY("1/1/1901", 2)')).toMatchObject({error: null, result: 2});
it("WEEKDAY", () => {
expect(parser.parse("WEEKDAY()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('WEEKDAY("1/1/1901")')).toMatchObject({
error: null,
result: 3,
});
expect(parser.parse('WEEKDAY("1/1/1901", 2)')).toMatchObject({
error: null,
result: 2,
});
});
it('WEEKNUM', () => {
expect(parser.parse('WEEKNUM()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('WEEKNUM("2/1/1900")')).toMatchObject({error: null, result: 5});
expect(parser.parse('WEEKNUM("2/1/1909", 2)')).toMatchObject({error: null, result: 6});
it("WEEKNUM", () => {
expect(parser.parse("WEEKNUM()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('WEEKNUM("2/1/1900")')).toMatchObject({
error: null,
result: 5,
});
expect(parser.parse('WEEKNUM("2/1/1909", 2)')).toMatchObject({
error: null,
result: 6,
});
});
it('WORKDAY', () => {
expect(parser.parse('WORKDAY()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('WORKDAY("1/1/1900")')).toMatchObject({error: '#VALUE!', result: null});
it("WORKDAY", () => {
expect(parser.parse("WORKDAY()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('WORKDAY("1/1/1900")')).toMatchObject({
error: "#VALUE!",
result: null,
});
const {result, error} = parser.parse('WORKDAY("1/1/1900", 1)');
const { result, error } = parser.parse('WORKDAY("1/1/1900", 1)');
expect(error).toBeNull();
expect(result.getDate()).toBe(2);
});
it('YEAR', () => {
expect(parser.parse('YEAR()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('YEAR("1/1/1904")')).toMatchObject({error: null, result: 1904});
expect(parser.parse('YEAR("12/12/2001")')).toMatchObject({error: null, result: 2001});
it("YEAR", () => {
expect(parser.parse("YEAR()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('YEAR("1/1/1904")')).toMatchObject({
error: null,
result: 1904,
});
expect(parser.parse('YEAR("12/12/2001")')).toMatchObject({
error: null,
result: 2001,
});
});
it('YEARFRAC', () => {
expect(parser.parse('YEARFRAC()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('YEARFRAC("1/1/1904")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('YEARFRAC("1/1/1900", "1/2/1900")')).toMatchObject({error: null, result: 0.002777777777777778});
it("YEARFRAC", () => {
expect(parser.parse("YEARFRAC()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('YEARFRAC("1/1/1904")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('YEARFRAC("1/1/1900", "1/2/1900")')).toMatchObject({
error: null,
result: 0.002777777777777778,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() financial formulas', () => {
describe(".parse() financial formulas", () => {
let parser;
beforeEach(() => {
@ -10,255 +10,640 @@ describe('.parse() financial formulas', () => {
parser = null;
});
it('ACCRINT', () => {
expect(parser.parse('ACCRINT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ACCRINT("2/2/2012")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013")')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1, 1000)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1, 1000, 1)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1, 1000, 1, 0)')).toMatchObject({error: null, result: 183.88888888888889});
it("ACCRINT", () => {
expect(parser.parse("ACCRINT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('ACCRINT("2/2/2012")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('ACCRINT("2/2/2012", "3/30/2012")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(
parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013")')
).toMatchObject({ error: "#NUM!", result: null });
expect(
parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1)')
).toMatchObject({ error: "#NUM!", result: null });
expect(
parser.parse('ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1, 1000)')
).toMatchObject({ error: "#NUM!", result: null });
expect(
parser.parse(
'ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1, 1000, 1)'
)
).toMatchObject({ error: "#NUM!", result: null });
expect(
parser.parse(
'ACCRINT("2/2/2012", "3/30/2012", "12/4/2013", 0.1, 1000, 1, 0)'
)
).toMatchObject({ error: null, result: 183.88888888888889 });
});
it('CUMIPMT', () => {
expect(parser.parse('CUMIPMT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CUMIPMT(0.1/12)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CUMIPMT(0.1/12, 30*12)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CUMIPMT(0.1/12, 30*12, 100000)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('CUMIPMT(0.1/12, 30*12, 100000, 13)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('CUMIPMT(0.1/12, 30*12, 100000, 13, 24)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('CUMIPMT(0.1/12, 30*12, 100000, 13, 24, 0)')).toMatchObject({error: null, result: -9916.77251395708});
it("CUMIPMT", () => {
expect(parser.parse("CUMIPMT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CUMIPMT(0.1/12)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CUMIPMT(0.1/12, 30*12)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CUMIPMT(0.1/12, 30*12, 100000)")).toMatchObject({
error: "#NUM!",
result: null,
});
expect(parser.parse("CUMIPMT(0.1/12, 30*12, 100000, 13)")).toMatchObject({
error: "#NUM!",
result: null,
});
expect(
parser.parse("CUMIPMT(0.1/12, 30*12, 100000, 13, 24)")
).toMatchObject({ error: "#NUM!", result: null });
expect(
parser.parse("CUMIPMT(0.1/12, 30*12, 100000, 13, 24, 0)")
).toMatchObject({ error: null, result: -9916.77251395708 });
});
it('CUMPRINC', () => {
expect(parser.parse('CUMPRINC()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CUMPRINC(0.1/12)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CUMPRINC(0.1/12, 30*12)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CUMPRINC(0.1/12, 30*12, 100000)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('CUMPRINC(0.1/12, 30*12, 100000, 13)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('CUMPRINC(0.1/12, 30*12, 100000, 13, 24)')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse('CUMPRINC(0.1/12, 30*12, 100000, 13, 24, 0)')).toMatchObject({error: null, result: -614.0863271085149});
it("CUMPRINC", () => {
expect(parser.parse("CUMPRINC()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CUMPRINC(0.1/12)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CUMPRINC(0.1/12, 30*12)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CUMPRINC(0.1/12, 30*12, 100000)")).toMatchObject({
error: "#NUM!",
result: null,
});
expect(parser.parse("CUMPRINC(0.1/12, 30*12, 100000, 13)")).toMatchObject({
error: "#NUM!",
result: null,
});
expect(
parser.parse("CUMPRINC(0.1/12, 30*12, 100000, 13, 24)")
).toMatchObject({ error: "#NUM!", result: null });
expect(
parser.parse("CUMPRINC(0.1/12, 30*12, 100000, 13, 24, 0)")
).toMatchObject({ error: null, result: -614.0863271085149 });
});
it('DB', () => {
expect(parser.parse('DB()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DB(10000)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DB(10000, 1000)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DB(10000, 1000, 6)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DB(10000, 1000, 6, 1)')).toMatchObject({error: null, result: 3190});
it("DB", () => {
expect(parser.parse("DB()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DB(10000)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DB(10000, 1000)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DB(10000, 1000, 6)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DB(10000, 1000, 6, 1)")).toMatchObject({
error: null,
result: 3190,
});
});
it('DDB', () => {
expect(parser.parse('DDB()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DDB(10000)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DDB(10000, 1000)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DDB(10000, 1000, 6)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DDB(10000, 1000, 6, 1)')).toMatchObject({error: null, result: 3333.333333333333});
it("DDB", () => {
expect(parser.parse("DDB()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DDB(10000)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DDB(10000, 1000)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DDB(10000, 1000, 6)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DDB(10000, 1000, 6, 1)")).toMatchObject({
error: null,
result: 3333.333333333333,
});
});
it('DOLLARDE', () => {
expect(parser.parse('DOLLARDE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DOLLARDE(1.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DOLLARDE(1.1, 4)')).toMatchObject({error: null, result: 1.25});
it("DOLLARDE", () => {
expect(parser.parse("DOLLARDE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DOLLARDE(1.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DOLLARDE(1.1, 4)")).toMatchObject({
error: null,
result: 1.25,
});
});
it('DOLLARFR', () => {
expect(parser.parse('DOLLARFR()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DOLLARFR(1.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DOLLARFR(1.1, 4)')).toMatchObject({error: null, result: 1.04});
it("DOLLARFR", () => {
expect(parser.parse("DOLLARFR()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DOLLARFR(1.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DOLLARFR(1.1, 4)")).toMatchObject({
error: null,
result: 1.04,
});
});
it('EFFECT', () => {
expect(parser.parse('EFFECT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('EFFECT(1.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('EFFECT(1.1, 4)')).toBeMatchCloseTo({error: null, result: 1.6426566406249994});
it("EFFECT", () => {
expect(parser.parse("EFFECT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("EFFECT(1.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("EFFECT(1.1, 4)")).toBeMatchCloseTo({
error: null,
result: 1.6426566406249994,
});
});
it('FV', () => {
expect(parser.parse('FV()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('FV(1.1, 10)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('FV(1.1, 10, -200)')).toMatchObject({error: null, result: 303088.7450582});
expect(parser.parse('FV(1.1, 10, -200, -500)')).toMatchObject({error: null, result: 1137082.79396825});
expect(parser.parse('FV(1.1, 10, -200, -500, 1)')).toMatchObject({error: null, result: 1470480.4135322701});
it("FV", () => {
expect(parser.parse("FV()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("FV(1.1, 10)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("FV(1.1, 10, -200)")).toMatchObject({
error: null,
result: 303088.7450582,
});
expect(parser.parse("FV(1.1, 10, -200, -500)")).toMatchObject({
error: null,
result: 1137082.79396825,
});
expect(parser.parse("FV(1.1, 10, -200, -500, 1)")).toMatchObject({
error: null,
result: 1470480.4135322701,
});
});
it('FVSCHEDULE', () => {
parser.on('callRangeValue', (a, b, done) => done([[0.09, 0.1, 0.11]]));
it("FVSCHEDULE", () => {
parser.on("callRangeValue", (a, b, done) => done([[0.09, 0.1, 0.11]]));
expect(parser.parse('FVSCHEDULE(100, A1:C1)')).toMatchObject({error: null, result: 133.08900000000003});
expect(parser.parse("FVSCHEDULE(100, A1:C1)")).toMatchObject({
error: null,
result: 133.08900000000003,
});
});
it('IPMT', () => {
expect(parser.parse('IPMT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('IPMT(0.2, 6)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('IPMT(0.2, 6, 24)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('IPMT(0.2, 6, 24, 1000)')).toMatchObject({error: null, result: -196.20794961065468});
expect(parser.parse('IPMT(0.2, 6, 24, 1000, 200)')).toMatchObject({error: null, result: -195.44953953278565});
expect(parser.parse('IPMT(0.2, 6, 24, 1000, 200, 1)')).toMatchObject({error: null, result: -162.87461627732137});
it("IPMT", () => {
expect(parser.parse("IPMT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("IPMT(0.2, 6)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("IPMT(0.2, 6, 24)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("IPMT(0.2, 6, 24, 1000)")).toMatchObject({
error: null,
result: -196.20794961065468,
});
expect(parser.parse("IPMT(0.2, 6, 24, 1000, 200)")).toMatchObject({
error: null,
result: -195.44953953278565,
});
expect(parser.parse("IPMT(0.2, 6, 24, 1000, 200, 1)")).toMatchObject({
error: null,
result: -162.87461627732137,
});
});
it('IRR', () => {
parser.on('callRangeValue', (a, b, done) => done([[-75000, 12000, 15000, 18000, 21000, 24000]]));
it("IRR", () => {
parser.on("callRangeValue", (a, b, done) =>
done([[-75000, 12000, 15000, 18000, 21000, 24000]])
);
expect(parser.parse('IRR(A1:C1)')).toMatchObject({error: null, result: 0.05715142887178453});
expect(parser.parse("IRR(A1:C1)")).toMatchObject({
error: null,
result: 0.05715142887178453,
});
});
it('ISPMT', () => {
expect(parser.parse('ISPMT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ISPMT(1.1, 2)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ISPMT(1.1, 2, 16)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ISPMT(1.1, 2, 16)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('ISPMT(1.1, 2, 16, 1000)')).toMatchObject({error: null, result: -962.5});
it("ISPMT", () => {
expect(parser.parse("ISPMT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("ISPMT(1.1, 2)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("ISPMT(1.1, 2, 16)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("ISPMT(1.1, 2, 16)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("ISPMT(1.1, 2, 16, 1000)")).toMatchObject({
error: null,
result: -962.5,
});
});
it('MIRR', () => {
parser.on('callRangeValue', (a, b, done) => done([[-75000, 12000, 15000, 18000, 21000, 24000]]));
it("MIRR", () => {
parser.on("callRangeValue", (a, b, done) =>
done([[-75000, 12000, 15000, 18000, 21000, 24000]])
);
expect(parser.parse('MIRR(A1:C1, 0.1, 0.12)')).toBeMatchCloseTo({error: null, result: 0.07971710360838036});
expect(parser.parse("MIRR(A1:C1, 0.1, 0.12)")).toBeMatchCloseTo({
error: null,
result: 0.07971710360838036,
});
});
it('NOMINAL', () => {
expect(parser.parse('NOMINAL()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NOMINAL(1.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NOMINAL(1.1, 2)')).toBeMatchCloseTo({error: null, result: 0.8982753492378879});
it("NOMINAL", () => {
expect(parser.parse("NOMINAL()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("NOMINAL(1.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("NOMINAL(1.1, 2)")).toBeMatchCloseTo({
error: null,
result: 0.8982753492378879,
});
});
it('NPER', () => {
expect(parser.parse('NPER()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NPER(1.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NPER(1.1, -2)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NPER(1.1, -2, -100)')).toBeMatchCloseTo({error: null, result: -5.4254604102768305});
expect(parser.parse('NPER(1.1, -2, -100, 1000)')).toBeMatchCloseTo({error: null, result: 3.081639082679854});
expect(parser.parse('NPER(1.1, -2, -100, 1000, 1)')).toBeMatchCloseTo({error: null, result: 3.058108732153963});
it("NPER", () => {
expect(parser.parse("NPER()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("NPER(1.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("NPER(1.1, -2)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("NPER(1.1, -2, -100)")).toBeMatchCloseTo({
error: null,
result: -5.4254604102768305,
});
expect(parser.parse("NPER(1.1, -2, -100, 1000)")).toBeMatchCloseTo({
error: null,
result: 3.081639082679854,
});
expect(parser.parse("NPER(1.1, -2, -100, 1000, 1)")).toBeMatchCloseTo({
error: null,
result: 3.058108732153963,
});
});
it('NPV', () => {
expect(parser.parse('NPV()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('NPV(1.1)')).toMatchObject({error: null, result: 0});
expect(parser.parse('NPV(1.1, -2)')).toBeMatchCloseTo({error: null, result: -0.9523809523809523});
expect(parser.parse('NPV(1.1, -2, -100)')).toBeMatchCloseTo({error: null, result: -23.6281179138322});
expect(parser.parse('NPV(1.1, -2, -100, 1000)')).toBeMatchCloseTo({error: null, result: 84.3515819026023});
expect(parser.parse('NPV(1.1, -2, -100, 1000, 1)')).toBeMatchCloseTo({error: null, result: 84.4030008072768});
it("NPV", () => {
expect(parser.parse("NPV()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("NPV(1.1)")).toMatchObject({ error: null, result: 0 });
expect(parser.parse("NPV(1.1, -2)")).toBeMatchCloseTo({
error: null,
result: -0.9523809523809523,
});
expect(parser.parse("NPV(1.1, -2, -100)")).toBeMatchCloseTo({
error: null,
result: -23.6281179138322,
});
expect(parser.parse("NPV(1.1, -2, -100, 1000)")).toBeMatchCloseTo({
error: null,
result: 84.3515819026023,
});
expect(parser.parse("NPV(1.1, -2, -100, 1000, 1)")).toBeMatchCloseTo({
error: null,
result: 84.4030008072768,
});
});
it('PDURATION', () => {
expect(parser.parse('PDURATION()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PDURATION(0.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PDURATION(0.1, 200)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PDURATION(0.1, 200, 400)')).toBeMatchCloseTo({error: null, result: 7.272540897341714});
it("PDURATION", () => {
expect(parser.parse("PDURATION()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PDURATION(0.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PDURATION(0.1, 200)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PDURATION(0.1, 200, 400)")).toBeMatchCloseTo({
error: null,
result: 7.272540897341714,
});
});
it('PMT', () => {
expect(parser.parse('PMT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PMT(0.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PMT(0.1, 200)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PMT(0.1, 200, 400)')).toBeMatchCloseTo({error: null, result: -40.00000021063133});
expect(parser.parse('PMT(0.1, 200, 400, 500)')).toBeMatchCloseTo({error: null, result: -40.00000047392049});
it("PMT", () => {
expect(parser.parse("PMT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PMT(0.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PMT(0.1, 200)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PMT(0.1, 200, 400)")).toBeMatchCloseTo({
error: null,
result: -40.00000021063133,
});
expect(parser.parse("PMT(0.1, 200, 400, 500)")).toBeMatchCloseTo({
error: null,
result: -40.00000047392049,
});
});
it('PPMT', () => {
expect(parser.parse('PPMT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PPMT(0.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PPMT(0.1, 200)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PPMT(0.1, 200, 400)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PPMT(0.1, 200, 400, 5000)')).toBeMatchCloseTo({error: null, result: 0.000012207031261368684});
it("PPMT", () => {
expect(parser.parse("PPMT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PPMT(0.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PPMT(0.1, 200)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PPMT(0.1, 200, 400)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PPMT(0.1, 200, 400, 5000)")).toBeMatchCloseTo({
error: null,
result: 0.000012207031261368684,
});
});
it('PV', () => {
expect(parser.parse('PV()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PV(1.1)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PV(1.1, 200)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PV(1.1, 200, 400)')).toBeMatchCloseTo({error: null, result: -363.6363636363636});
expect(parser.parse('PV(1.1, 200, 400, 5000)')).toBeMatchCloseTo({error: null, result: -363.6363636363636});
expect(parser.parse('PV(1.1, 200, 400, 5000, 1)')).toBeMatchCloseTo({error: null, result: -763.6363636363636});
it("PV", () => {
expect(parser.parse("PV()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PV(1.1)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PV(1.1, 200)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PV(1.1, 200, 400)")).toBeMatchCloseTo({
error: null,
result: -363.6363636363636,
});
expect(parser.parse("PV(1.1, 200, 400, 5000)")).toBeMatchCloseTo({
error: null,
result: -363.6363636363636,
});
expect(parser.parse("PV(1.1, 200, 400, 5000, 1)")).toBeMatchCloseTo({
error: null,
result: -763.6363636363636,
});
});
it('RATE', () => {
expect(parser.parse('RATE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('RATE(24)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('RATE(24, -1000)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('RATE(24, -1000, -10000)')).toBeMatchCloseTo({error: null, result: -1.2079096886965142});
expect(parser.parse('RATE(24, -1000, -10000, 10000)')).toMatchObject({error: null, result: -0.1});
expect(parser.parse('RATE(24, -1000, -10000, 10000, 1)')).toBeMatchCloseTo({error: null, result: -0.09090909090909093});
expect(parser.parse('RATE(24, -1000, -10000, 10000, 1, 0.1)')).toBeMatchCloseTo({error: null, result: -0.09090909090909091});
it("RATE", () => {
expect(parser.parse("RATE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("RATE(24)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("RATE(24, -1000)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("RATE(24, -1000, -10000)")).toBeMatchCloseTo({
error: null,
result: -1.2079096886965142,
});
expect(parser.parse("RATE(24, -1000, -10000, 10000)")).toMatchObject({
error: null,
result: -0.1,
});
expect(parser.parse("RATE(24, -1000, -10000, 10000, 1)")).toBeMatchCloseTo({
error: null,
result: -0.09090909090909093,
});
expect(
parser.parse("RATE(24, -1000, -10000, 10000, 1, 0.1)")
).toBeMatchCloseTo({ error: null, result: -0.09090909090909091 });
});
it('RRI', () => {
expect(parser.parse('RRI()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('RRI(8)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('RRI(8, 100)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('RRI(8, 100, 300)')).toBeMatchCloseTo({error: null, result: 0.1472026904398771});
it("RRI", () => {
expect(parser.parse("RRI()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("RRI(8)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("RRI(8, 100)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("RRI(8, 100, 300)")).toBeMatchCloseTo({
error: null,
result: 0.1472026904398771,
});
});
it('SLN', () => {
expect(parser.parse('SLN()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SLN(200)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SLN(200, 750)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SLN(200, 750, 10)')).toMatchObject({error: null, result: -55});
it("SLN", () => {
expect(parser.parse("SLN()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SLN(200)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SLN(200, 750)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SLN(200, 750, 10)")).toMatchObject({
error: null,
result: -55,
});
});
it('SYD', () => {
expect(parser.parse('SYD()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SYD(200)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SYD(200, 750)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SYD(200, 750, 10)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SYD(200, 750, 10, 1)')).toMatchObject({error: null, result: -100});
it("SYD", () => {
expect(parser.parse("SYD()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SYD(200)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SYD(200, 750)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SYD(200, 750, 10)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("SYD(200, 750, 10, 1)")).toMatchObject({
error: null,
result: -100,
});
});
it('TBILLEQ', () => {
expect(parser.parse('TBILLEQ()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLEQ("03/31/2008")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLEQ("03/31/2008", "06/01/2008")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLEQ("03/31/2008", "06/01/2008", 0.09)')).toBeMatchCloseTo({error: null, result: 0.09266311246509266});
it("TBILLEQ", () => {
expect(parser.parse("TBILLEQ()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('TBILLEQ("03/31/2008")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('TBILLEQ("03/31/2008", "06/01/2008")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(
parser.parse('TBILLEQ("03/31/2008", "06/01/2008", 0.09)')
).toBeMatchCloseTo({ error: null, result: 0.09266311246509266 });
});
it('TBILLPRICE', () => {
expect(parser.parse('TBILLPRICE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLPRICE("03/31/2008")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLPRICE("03/31/2008", "06/01/2008")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLPRICE("03/31/2008", "06/01/2008", 0.09)')).toBeMatchCloseTo({error: null, result: 98.475});
it("TBILLPRICE", () => {
expect(parser.parse("TBILLPRICE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('TBILLPRICE("03/31/2008")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(
parser.parse('TBILLPRICE("03/31/2008", "06/01/2008")')
).toMatchObject({ error: "#VALUE!", result: null });
expect(
parser.parse('TBILLPRICE("03/31/2008", "06/01/2008", 0.09)')
).toBeMatchCloseTo({ error: null, result: 98.475 });
});
it('TBILLYIELD', () => {
expect(parser.parse('TBILLYIELD()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLYIELD("03/31/2008")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLYIELD("03/31/2008", "06/01/2008")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TBILLYIELD("03/31/2008", "06/01/2008", 0.09)')).toBeMatchCloseTo({error: null, result: 6551.475409836065});
it("TBILLYIELD", () => {
expect(parser.parse("TBILLYIELD()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('TBILLYIELD("03/31/2008")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(
parser.parse('TBILLYIELD("03/31/2008", "06/01/2008")')
).toMatchObject({ error: "#VALUE!", result: null });
expect(
parser.parse('TBILLYIELD("03/31/2008", "06/01/2008", 0.09)')
).toBeMatchCloseTo({ error: null, result: 6551.475409836065 });
});
// TODO: Not supported yet
xit('XIRR', () => {
parser.on('callRangeValue', (a, b, done) => {
xit("XIRR", () => {
parser.on("callRangeValue", (a, b, done) => {
let values;
if (a.label === 'A1' && b.label === 'C1') {
if (a.label === "A1" && b.label === "C1") {
values = [[-10000, 2750, 4250, 3250, 2750]];
} else if (a.label === 'A2' && b.label === 'C2') {
values = [['01/jan/08', '01/mar/08', '30/oct/08', '15/feb/09', '01/apr/09']];
} else if (a.label === "A2" && b.label === "C2") {
values = [
["01/jan/08", "01/mar/08", "30/oct/08", "15/feb/09", "01/apr/09"],
];
}
done(values);
});
expect(parser.parse('XIRR(A1:C1, A2:C2, 0.1)')).toBeMatchCloseTo({error: null, result: 0.373374019797564});
expect(parser.parse("XIRR(A1:C1, A2:C2, 0.1)")).toBeMatchCloseTo({
error: null,
result: 0.373374019797564,
});
});
it('XNPV', () => {
parser.on('callRangeValue', (a, b, done) => {
it("XNPV", () => {
parser.on("callRangeValue", (a, b, done) => {
let values;
if (a.label === 'A1' && b.label === 'C1') {
if (a.label === "A1" && b.label === "C1") {
values = [[-10000, 2750, 4250, 3250, 2750]];
} else if (a.label === 'A2' && b.label === 'C2') {
values = [['01/01/2008', '03/01/2008', '10/30/2008', '02/15/2009', '04/01/2009']];
} else if (a.label === "A2" && b.label === "C2") {
values = [
[
"01/01/2008",
"03/01/2008",
"10/30/2008",
"02/15/2009",
"04/01/2009",
],
];
}
done(values);
});
expect(parser.parse('XNPV(0.09, A1:C1, A2:C2)')).toBeMatchCloseTo({error: null, result: 2086.6718943024616});
expect(parser.parse("XNPV(0.09, A1:C1, A2:C2)")).toBeMatchCloseTo({
error: null,
result: 2086.6718943024616,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() information formulas', () => {
describe(".parse() information formulas", () => {
let parser;
beforeEach(() => {
@ -10,60 +10,159 @@ describe('.parse() information formulas', () => {
parser = null;
});
it('ISBINARY', () => {
expect(parser.parse('ISBINARY()')).toMatchObject({error: null, result: false});
expect(parser.parse('ISBINARY(1)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISBINARY(0)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISBINARY("1010")')).toMatchObject({error: null, result: true});
it("ISBINARY", () => {
expect(parser.parse("ISBINARY()")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISBINARY(1)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISBINARY(0)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('ISBINARY("1010")')).toMatchObject({
error: null,
result: true,
});
});
it('ISBLANK', () => {
expect(parser.parse('ISBLANK(NULL)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISBLANK(FALSE)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISBLANK(0)')).toMatchObject({error: null, result: false});
it("ISBLANK", () => {
expect(parser.parse("ISBLANK(NULL)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISBLANK(FALSE)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISBLANK(0)")).toMatchObject({
error: null,
result: false,
});
});
it('ISEVEN', () => {
expect(parser.parse('ISEVEN(1)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISEVEN(2)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISEVEN(2.5)')).toMatchObject({error: null, result: true});
it("ISEVEN", () => {
expect(parser.parse("ISEVEN(1)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISEVEN(2)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISEVEN(2.5)")).toMatchObject({
error: null,
result: true,
});
});
it('ISLOGICAL', () => {
expect(parser.parse('ISLOGICAL(1)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISLOGICAL(TRUE)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISLOGICAL(FALSE)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISLOGICAL(NULL)')).toMatchObject({error: null, result: false});
it("ISLOGICAL", () => {
expect(parser.parse("ISLOGICAL(1)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISLOGICAL(TRUE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISLOGICAL(FALSE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISLOGICAL(NULL)")).toMatchObject({
error: null,
result: false,
});
});
it('ISNONTEXT', () => {
expect(parser.parse('ISNONTEXT()')).toMatchObject({error: null, result: true});
expect(parser.parse('ISNONTEXT(1)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISNONTEXT(TRUE)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISNONTEXT("FALSE")')).toMatchObject({error: null, result: false});
expect(parser.parse('ISNONTEXT("foo")')).toMatchObject({error: null, result: false});
it("ISNONTEXT", () => {
expect(parser.parse("ISNONTEXT()")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISNONTEXT(1)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISNONTEXT(TRUE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('ISNONTEXT("FALSE")')).toMatchObject({
error: null,
result: false,
});
expect(parser.parse('ISNONTEXT("foo")')).toMatchObject({
error: null,
result: false,
});
});
it('ISNUMBER', () => {
expect(parser.parse('ISNUMBER()')).toMatchObject({error: null, result: false});
expect(parser.parse('ISNUMBER(1)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISNUMBER(0.142342)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISNUMBER(TRUE)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISNUMBER("FALSE")')).toMatchObject({error: null, result: false});
expect(parser.parse('ISNUMBER("foo")')).toMatchObject({error: null, result: false});
it("ISNUMBER", () => {
expect(parser.parse("ISNUMBER()")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISNUMBER(1)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISNUMBER(0.142342)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISNUMBER(TRUE)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse('ISNUMBER("FALSE")')).toMatchObject({
error: null,
result: false,
});
expect(parser.parse('ISNUMBER("foo")')).toMatchObject({
error: null,
result: false,
});
});
it('ISODD', () => {
expect(parser.parse('ISODD(1)')).toMatchObject({error: null, result: true});
expect(parser.parse('ISODD(2)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISODD(2.5)')).toMatchObject({error: null, result: false});
it("ISODD", () => {
expect(parser.parse("ISODD(1)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("ISODD(2)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISODD(2.5)")).toMatchObject({
error: null,
result: false,
});
});
it('ISTEXT', () => {
expect(parser.parse('ISTEXT()')).toMatchObject({error: null, result: false});
expect(parser.parse('ISTEXT(1)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISTEXT(TRUE)')).toMatchObject({error: null, result: false});
expect(parser.parse('ISTEXT("FALSE")')).toMatchObject({error: null, result: true});
expect(parser.parse('ISTEXT("foo")')).toMatchObject({error: null, result: true});
it("ISTEXT", () => {
expect(parser.parse("ISTEXT()")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISTEXT(1)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("ISTEXT(TRUE)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse('ISTEXT("FALSE")')).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('ISTEXT("foo")')).toMatchObject({
error: null,
result: true,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() logical formulas', () => {
describe(".parse() logical formulas", () => {
let parser;
beforeEach(() => {
@ -10,60 +10,129 @@ describe('.parse() logical formulas', () => {
parser = null;
});
it('AND', () => {
expect(parser.parse('AND()')).toMatchObject({error: null, result: true});
expect(parser.parse('AND(TRUE, TRUE, FALSE)')).toMatchObject({error: null, result: false});
expect(parser.parse('AND(TRUE, TRUE, TRUE)')).toMatchObject({error: null, result: true});
it("AND", () => {
expect(parser.parse("AND()")).toMatchObject({ error: null, result: true });
expect(parser.parse("AND(TRUE, TRUE, FALSE)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("AND(TRUE, TRUE, TRUE)")).toMatchObject({
error: null,
result: true,
});
});
it('CHOOSE', () => {
expect(parser.parse('CHOOSE()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('CHOOSE(1, "foo", "bar", "baz")')).toMatchObject({error: null, result: 'foo'});
expect(parser.parse('CHOOSE(3, "foo", "bar", "baz")')).toMatchObject({error: null, result: 'baz'});
expect(parser.parse('CHOOSE(4, "foo", "bar", "baz")')).toMatchObject({error: '#VALUE!', result: null});
it("CHOOSE", () => {
expect(parser.parse("CHOOSE()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('CHOOSE(1, "foo", "bar", "baz")')).toMatchObject({
error: null,
result: "foo",
});
expect(parser.parse('CHOOSE(3, "foo", "bar", "baz")')).toMatchObject({
error: null,
result: "baz",
});
expect(parser.parse('CHOOSE(4, "foo", "bar", "baz")')).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('FALSE', () => {
expect(parser.parse('FALSE()')).toMatchObject({error: null, result: false});
it("FALSE", () => {
expect(parser.parse("FALSE()")).toMatchObject({
error: null,
result: false,
});
});
it('IF', () => {
expect(parser.parse('IF()')).toMatchObject({error: null, result: true});
expect(parser.parse('IF(TRUE, 1, 2)')).toMatchObject({error: null, result: 1});
expect(parser.parse('IF(FALSE, 1, 2)')).toMatchObject({error: null, result: 2});
it("IF", () => {
expect(parser.parse("IF()")).toMatchObject({ error: null, result: true });
expect(parser.parse("IF(TRUE, 1, 2)")).toMatchObject({
error: null,
result: 1,
});
expect(parser.parse("IF(FALSE, 1, 2)")).toMatchObject({
error: null,
result: 2,
});
});
it('NOT', () => {
expect(parser.parse('NOT()')).toMatchObject({error: null, result: true});
expect(parser.parse('NOT(TRUE)')).toMatchObject({error: null, result: false});
expect(parser.parse('NOT(FALSE)')).toMatchObject({error: null, result: true});
expect(parser.parse('NOT(0)')).toMatchObject({error: null, result: true});
expect(parser.parse('NOT(1)')).toMatchObject({error: null, result: false});
it("NOT", () => {
expect(parser.parse("NOT()")).toMatchObject({ error: null, result: true });
expect(parser.parse("NOT(TRUE)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("NOT(FALSE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("NOT(0)")).toMatchObject({ error: null, result: true });
expect(parser.parse("NOT(1)")).toMatchObject({
error: null,
result: false,
});
});
it('OR', () => {
expect(parser.parse('OR()')).toMatchObject({error: null, result: false});
expect(parser.parse('OR(TRUE, TRUE, TRUE)')).toMatchObject({error: null, result: true});
expect(parser.parse('OR(TRUE, FALSE, FALSE)')).toMatchObject({error: null, result: true});
expect(parser.parse('OR(FALSE, FALSE, FALSE)')).toMatchObject({error: null, result: false});
it("OR", () => {
expect(parser.parse("OR()")).toMatchObject({ error: null, result: false });
expect(parser.parse("OR(TRUE, TRUE, TRUE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("OR(TRUE, FALSE, FALSE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("OR(FALSE, FALSE, FALSE)")).toMatchObject({
error: null,
result: false,
});
});
it('TRUE', () => {
expect(parser.parse('TRUE()')).toMatchObject({error: null, result: true});
it("TRUE", () => {
expect(parser.parse("TRUE()")).toMatchObject({ error: null, result: true });
});
it('XOR', () => {
expect(parser.parse('XOR()')).toMatchObject({error: null, result: false});
expect(parser.parse('XOR(TRUE, TRUE)')).toMatchObject({error: null, result: false});
expect(parser.parse('XOR(TRUE, FALSE)')).toMatchObject({error: null, result: true});
expect(parser.parse('XOR(FALSE, TRUE)')).toMatchObject({error: null, result: true});
expect(parser.parse('XOR(FALSE, FALSE)')).toMatchObject({error: null, result: false});
it("XOR", () => {
expect(parser.parse("XOR()")).toMatchObject({ error: null, result: false });
expect(parser.parse("XOR(TRUE, TRUE)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("XOR(TRUE, FALSE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("XOR(FALSE, TRUE)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("XOR(FALSE, FALSE)")).toMatchObject({
error: null,
result: false,
});
});
it('SWITCH', () => {
expect(parser.parse('SWITCH()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SWITCH(7, "foo")')).toMatchObject({error: null, result: 'foo'});
expect(parser.parse('SWITCH(7, 9, "foo", 7, "bar")')).toMatchObject({error: null, result: 'bar'});
expect(parser.parse('SWITCH(10, 9, "foo", 7, "bar")')).toMatchObject({error: '#N/A', result: null});
it("SWITCH", () => {
expect(parser.parse("SWITCH()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('SWITCH(7, "foo")')).toMatchObject({
error: null,
result: "foo",
});
expect(parser.parse('SWITCH(7, 9, "foo", 7, "bar")')).toMatchObject({
error: null,
result: "bar",
});
expect(parser.parse('SWITCH(10, 9, "foo", 7, "bar")')).toMatchObject({
error: "#N/A",
result: null,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() lookup-reference formulas', () => {
describe(".parse() lookup-reference formulas", () => {
let parser;
beforeEach(() => {
@ -10,16 +10,37 @@ describe('.parse() lookup-reference formulas', () => {
parser = null;
});
it('MATCH', () => {
parser.setVariable('foo', [0, 1, 2, 3, 4, 100, 7]);
parser.setVariable('bar', ['jima', 'jimb', 'jimc', 'bernie']);
it("MATCH", () => {
parser.setVariable("foo", [0, 1, 2, 3, 4, 100, 7]);
parser.setVariable("bar", ["jima", "jimb", "jimc", "bernie"]);
expect(parser.parse('MATCH()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('MATCH(1)')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('MATCH(1, foo)')).toMatchObject({error: null, result: 2});
expect(parser.parse('MATCH(4, foo, 1)')).toMatchObject({error: null, result: 5});
expect(parser.parse('MATCH("jima", bar, 0)')).toMatchObject({error: null, result: 1});
expect(parser.parse('MATCH("j?b", bar, 0)')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('MATCH("jimc", bar, 0)')).toMatchObject({error: null, result: 3});
expect(parser.parse("MATCH()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse("MATCH(1)")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse("MATCH(1, foo)")).toMatchObject({
error: null,
result: 2,
});
expect(parser.parse("MATCH(4, foo, 1)")).toMatchObject({
error: null,
result: 5,
});
expect(parser.parse('MATCH("jima", bar, 0)')).toMatchObject({
error: null,
result: 1,
});
expect(parser.parse('MATCH("j?b", bar, 0)')).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('MATCH("jimc", bar, 0)')).toMatchObject({
error: null,
result: 3,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() miscellaneous formulas', () => {
describe(".parse() miscellaneous formulas", () => {
let parser;
beforeEach(() => {
@ -10,51 +10,84 @@ describe('.parse() miscellaneous formulas', () => {
parser = null;
});
it('UNIQUE', () => {
expect(parser.parse('UNIQUE()')).toMatchObject({error: null, result: []});
expect(parser.parse('UNIQUE(1, 2, 3, 4, 4, 4, 4, 3)')).toMatchObject({error: null, result: [1, 2, 3, 4]});
expect(parser.parse('UNIQUE("foo", "bar", "foo")')).toMatchObject({error: null, result: ['foo', 'bar']});
it("UNIQUE", () => {
expect(parser.parse("UNIQUE()")).toMatchObject({ error: null, result: [] });
expect(parser.parse("UNIQUE(1, 2, 3, 4, 4, 4, 4, 3)")).toMatchObject({
error: null,
result: [1, 2, 3, 4],
});
expect(parser.parse('UNIQUE("foo", "bar", "foo")')).toMatchObject({
error: null,
result: ["foo", "bar"],
});
});
it('ARGS2ARRAY', () => {
expect(parser.parse('ARGS2ARRAY()')).toMatchObject({error: null, result: []});
expect(parser.parse('ARGS2ARRAY(1, 4, 4, 3)')).toMatchObject({error: null, result: [1, 4, 4, 3]});
expect(parser.parse('ARGS2ARRAY("foo", "bar", "foo")')).toMatchObject({error: null, result: ['foo', 'bar', 'foo']});
it("ARGS2ARRAY", () => {
expect(parser.parse("ARGS2ARRAY()")).toMatchObject({
error: null,
result: [],
});
expect(parser.parse("ARGS2ARRAY(1, 4, 4, 3)")).toMatchObject({
error: null,
result: [1, 4, 4, 3],
});
expect(parser.parse('ARGS2ARRAY("foo", "bar", "foo")')).toMatchObject({
error: null,
result: ["foo", "bar", "foo"],
});
});
it('FLATTEN', () => {
parser.on('callRangeValue', (a, b, done) => {
if (a.label === 'A1' && b.label === 'B3') {
it("FLATTEN", () => {
parser.on("callRangeValue", (a, b, done) => {
if (a.label === "A1" && b.label === "B3") {
done([[1, 2, [3], [4, 5]]]);
}
});
expect(parser.parse('FLATTEN(A1:B3)')).toMatchObject({error: null, result: [1, 2, 3, 4, 5]});
expect(parser.parse("FLATTEN(A1:B3)")).toMatchObject({
error: null,
result: [1, 2, 3, 4, 5],
});
});
it('JOIN', () => {
parser.on('callRangeValue', (a, b, done) => {
if (a.label === 'A1' && b.label === 'B3') {
it("JOIN", () => {
parser.on("callRangeValue", (a, b, done) => {
if (a.label === "A1" && b.label === "B3") {
done([[1, 2, [3], [4, 5]]]);
}
});
expect(parser.parse('JOIN(A1:B3)')).toMatchObject({error: null, result: '1,2,3,4,5'});
expect(parser.parse("JOIN(A1:B3)")).toMatchObject({
error: null,
result: "1,2,3,4,5",
});
});
it('NUMBERS', () => {
expect(parser.parse('NUMBERS()')).toMatchObject({error: null, result: []});
expect(parser.parse('NUMBERS(1, "4", "4", 3)')).toMatchObject({error: null, result: [1, 3]});
expect(parser.parse('NUMBERS("foo", 2, "bar", "foo")')).toMatchObject({error: null, result: [2]});
it("NUMBERS", () => {
expect(parser.parse("NUMBERS()")).toMatchObject({
error: null,
result: [],
});
expect(parser.parse('NUMBERS(1, "4", "4", 3)')).toMatchObject({
error: null,
result: [1, 3],
});
expect(parser.parse('NUMBERS("foo", 2, "bar", "foo")')).toMatchObject({
error: null,
result: [2],
});
});
it('REFERENCE', () => {
parser.on('callCellValue', (a, done) => {
if (a.label === 'A1') {
done({name: {firstName: 'Jim'}});
it("REFERENCE", () => {
parser.on("callCellValue", (a, done) => {
if (a.label === "A1") {
done({ name: { firstName: "Jim" } });
}
});
expect(parser.parse('REFERENCE(A1, "name.firstName")')).toMatchObject({error: null, result: 'Jim'});
expect(parser.parse('REFERENCE(A1, "name.firstName")')).toMatchObject({
error: null,
result: "Jim",
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../../src/parser';
import Parser from "../../../../src/parser";
describe('.parse() text formulas', () => {
describe(".parse() text formulas", () => {
let parser;
beforeEach(() => {
@ -10,195 +10,472 @@ describe('.parse() text formulas', () => {
parser = null;
});
it('CHAR', () => {
expect(parser.parse('CHAR()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('CHAR(33)')).toMatchObject({error: null, result: '!'});
it("CHAR", () => {
expect(parser.parse("CHAR()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("CHAR(33)")).toMatchObject({
error: null,
result: "!",
});
});
it('CLEAN', () => {
expect(parser.parse('CLEAN()')).toMatchObject({error: null, result: ''});
expect(parser.parse('CLEAN(CHAR(9)&"Monthly report"&CHAR(10))')).toMatchObject({error: null, result: 'Monthly report'});
it("CLEAN", () => {
expect(parser.parse("CLEAN()")).toMatchObject({ error: null, result: "" });
expect(
parser.parse('CLEAN(CHAR(9)&"Monthly report"&CHAR(10))')
).toMatchObject({ error: null, result: "Monthly report" });
});
it('CODE', () => {
expect(parser.parse('CODE()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('CODE("a")')).toMatchObject({error: null, result: 97});
it("CODE", () => {
expect(parser.parse("CODE()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('CODE("a")')).toMatchObject({
error: null,
result: 97,
});
});
it('CONCATENATE', () => {
expect(parser.parse('CONCATENATE()')).toMatchObject({error: null, result: ''});
expect(parser.parse('CONCATENATE("a")')).toMatchObject({error: null, result: 'a'});
expect(parser.parse('CONCATENATE("a", 1)')).toMatchObject({error: null, result: 'a1'});
expect(parser.parse('CONCATENATE("a", 1, TRUE)')).toMatchObject({error: null, result: 'a1TRUE'});
it("CONCATENATE", () => {
expect(parser.parse("CONCATENATE()")).toMatchObject({
error: null,
result: "",
});
expect(parser.parse('CONCATENATE("a")')).toMatchObject({
error: null,
result: "a",
});
expect(parser.parse('CONCATENATE("a", 1)')).toMatchObject({
error: null,
result: "a1",
});
expect(parser.parse('CONCATENATE("a", 1, TRUE)')).toMatchObject({
error: null,
result: "a1TRUE",
});
});
xit('DOLLAR', () => {
expect(parser.parse('DOLLAR()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('DOLLAR(1100)')).toMatchObject({error: null, result: '$1,100.00'});
expect(parser.parse('DOLLAR(1100, -2)')).toMatchObject({error: null, result: '$1,100'});
xit("DOLLAR", () => {
expect(parser.parse("DOLLAR()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("DOLLAR(1100)")).toMatchObject({
error: null,
result: "$1,100.00",
});
expect(parser.parse("DOLLAR(1100, -2)")).toMatchObject({
error: null,
result: "$1,100",
});
});
it('EXACT', () => {
expect(parser.parse('EXACT()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('EXACT(1100)')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('EXACT(1100, -2)')).toMatchObject({error: null, result: false});
expect(parser.parse('EXACT(1100, 1100)')).toMatchObject({error: null, result: true});
expect(parser.parse('EXACT(1100, "1100")')).toMatchObject({error: null, result: false});
it("EXACT", () => {
expect(parser.parse("EXACT()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse("EXACT(1100)")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse("EXACT(1100, -2)")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("EXACT(1100, 1100)")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('EXACT(1100, "1100")')).toMatchObject({
error: null,
result: false,
});
});
it('FIND', () => {
expect(parser.parse('FIND()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('FIND("o")')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('FIND("o", "FooBar")')).toMatchObject({error: null, result: 2});
expect(parser.parse('FIND("O", "FooBar")')).toMatchObject({error: null, result: 0});
it("FIND", () => {
expect(parser.parse("FIND()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('FIND("o")')).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('FIND("o", "FooBar")')).toMatchObject({
error: null,
result: 2,
});
expect(parser.parse('FIND("O", "FooBar")')).toMatchObject({
error: null,
result: 0,
});
});
xit('FIXED', () => {
expect(parser.parse('FIXED()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('FIXED(12345.11, -1)')).toMatchObject({error: null, result: '12,350'});
expect(parser.parse('FIXED(12345.11, 0)')).toMatchObject({error: null, result: '12,345'});
expect(parser.parse('FIXED(12345.11, 0, TRUE)')).toMatchObject({error: null, result: '12345'});
expect(parser.parse('FIXED(12345.11, 4, TRUE)')).toMatchObject({error: null, result: '12345.1100'});
xit("FIXED", () => {
expect(parser.parse("FIXED()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("FIXED(12345.11, -1)")).toMatchObject({
error: null,
result: "12,350",
});
expect(parser.parse("FIXED(12345.11, 0)")).toMatchObject({
error: null,
result: "12,345",
});
expect(parser.parse("FIXED(12345.11, 0, TRUE)")).toMatchObject({
error: null,
result: "12345",
});
expect(parser.parse("FIXED(12345.11, 4, TRUE)")).toMatchObject({
error: null,
result: "12345.1100",
});
});
it('HTML2TEXT', () => {
expect(parser.parse('HTML2TEXT()')).toMatchObject({error: null, result: ''});
expect(parser.parse('HTML2TEXT("Click <a>Link</a>")')).toMatchObject({error: null, result: 'Click Link'});
it("HTML2TEXT", () => {
expect(parser.parse("HTML2TEXT()")).toMatchObject({
error: null,
result: "",
});
expect(parser.parse('HTML2TEXT("Click <a>Link</a>")')).toMatchObject({
error: null,
result: "Click Link",
});
});
it('LEFT', () => {
expect(parser.parse('LEFT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('LEFT("Foo Bar")')).toMatchObject({error: null, result: 'F'});
expect(parser.parse('LEFT("Foo Bar", 3)')).toMatchObject({error: null, result: 'Foo'});
it("LEFT", () => {
expect(parser.parse("LEFT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('LEFT("Foo Bar")')).toMatchObject({
error: null,
result: "F",
});
expect(parser.parse('LEFT("Foo Bar", 3)')).toMatchObject({
error: null,
result: "Foo",
});
});
it('LEN', () => {
expect(parser.parse('LEN()')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('LEN(TRUE)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('LEN(1023)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('LEN("Foo Bar")')).toMatchObject({error: null, result: 7});
it("LEN", () => {
expect(parser.parse("LEN()")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse("LEN(TRUE)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("LEN(1023)")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('LEN("Foo Bar")')).toMatchObject({
error: null,
result: 7,
});
});
it('LOWER', () => {
expect(parser.parse('LOWER()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('LOWER("")')).toMatchObject({error: null, result: ''});
expect(parser.parse('LOWER("Foo Bar")')).toMatchObject({error: null, result: 'foo bar'});
it("LOWER", () => {
expect(parser.parse("LOWER()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('LOWER("")')).toMatchObject({
error: null,
result: "",
});
expect(parser.parse('LOWER("Foo Bar")')).toMatchObject({
error: null,
result: "foo bar",
});
});
it('MID', () => {
expect(parser.parse('MID()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('MID("")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('MID("Foo Bar", 2)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('MID("Foo Bar", 2, 5)')).toMatchObject({error: null, result: 'oo Ba'});
it("MID", () => {
expect(parser.parse("MID()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('MID("")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('MID("Foo Bar", 2)')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('MID("Foo Bar", 2, 5)')).toMatchObject({
error: null,
result: "oo Ba",
});
});
it('PROPER', () => {
expect(parser.parse('PROPER()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PROPER("")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('PROPER(TRUE)')).toMatchObject({error: null, result: 'True'});
expect(parser.parse('PROPER(1234)')).toMatchObject({error: null, result: '1234'});
expect(parser.parse('PROPER("foo bar")')).toMatchObject({error: null, result: 'Foo Bar'});
it("PROPER", () => {
expect(parser.parse("PROPER()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('PROPER("")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("PROPER(TRUE)")).toMatchObject({
error: null,
result: "True",
});
expect(parser.parse("PROPER(1234)")).toMatchObject({
error: null,
result: "1234",
});
expect(parser.parse('PROPER("foo bar")')).toMatchObject({
error: null,
result: "Foo Bar",
});
});
it('REGEXEXTRACT', () => {
expect(parser.parse('REGEXEXTRACT()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('REGEXEXTRACT("extract foo bar", "(foo)")')).toMatchObject({error: null, result: 'foo'});
expect(parser.parse('REGEXEXTRACT("pressure 12.21bar", "([0-9]+.[0-9]+)")')).toMatchObject({error: null, result: '12.21'});
it("REGEXEXTRACT", () => {
expect(parser.parse("REGEXEXTRACT()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(
parser.parse('REGEXEXTRACT("extract foo bar", "(foo)")')
).toMatchObject({ error: null, result: "foo" });
expect(
parser.parse('REGEXEXTRACT("pressure 12.21bar", "([0-9]+.[0-9]+)")')
).toMatchObject({ error: null, result: "12.21" });
});
it('REGEXREPLACE', () => {
expect(parser.parse('REGEXREPLACE()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('REGEXREPLACE("extract foo bar", "(foo)", "baz")')).toMatchObject({error: null, result: 'extract baz bar'});
expect(parser.parse('REGEXREPLACE("pressure 12.21bar", "([0-9]+.[0-9]+)", "43.1")')).toMatchObject({error: null, result: 'pressure 43.1bar'});
it("REGEXREPLACE", () => {
expect(parser.parse("REGEXREPLACE()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(
parser.parse('REGEXREPLACE("extract foo bar", "(foo)", "baz")')
).toMatchObject({ error: null, result: "extract baz bar" });
expect(
parser.parse(
'REGEXREPLACE("pressure 12.21bar", "([0-9]+.[0-9]+)", "43.1")'
)
).toMatchObject({ error: null, result: "pressure 43.1bar" });
});
it('REGEXMATCH', () => {
expect(parser.parse('REGEXMATCH()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('REGEXMATCH("pressure 12.21bar", "([0-9]+.[0-9]+)")')).toMatchObject({error: null, result: true});
it("REGEXMATCH", () => {
expect(parser.parse("REGEXMATCH()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(
parser.parse('REGEXMATCH("pressure 12.21bar", "([0-9]+.[0-9]+)")')
).toMatchObject({ error: null, result: true });
const result = parser.parse('REGEXMATCH("pressure 12.33bar", "([0-9]+.[0-9]+)", TRUE)');
const result = parser.parse(
'REGEXMATCH("pressure 12.33bar", "([0-9]+.[0-9]+)", TRUE)'
);
expect(result).toBeInstanceOf(Object);
});
it('REPLACE', () => {
expect(parser.parse('REPLACE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('REPLACE("foo bar")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('REPLACE("foo bar", 2)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('REPLACE("foo bar", 2, 5)')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('REPLACE("foo bar", 2, 5, "*")')).toMatchObject({error: null, result: 'f*r'});
it("REPLACE", () => {
expect(parser.parse("REPLACE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('REPLACE("foo bar")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('REPLACE("foo bar", 2)')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('REPLACE("foo bar", 2, 5)')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('REPLACE("foo bar", 2, 5, "*")')).toMatchObject({
error: null,
result: "f*r",
});
});
it('REPT', () => {
expect(parser.parse('REPT()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('REPT("foo ")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('REPT("foo ", 5)')).toMatchObject({error: null, result: 'foo foo foo foo foo '});
it("REPT", () => {
expect(parser.parse("REPT()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('REPT("foo ")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('REPT("foo ", 5)')).toMatchObject({
error: null,
result: "foo foo foo foo foo ",
});
});
it('RIGHT', () => {
expect(parser.parse('RIGHT()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('RIGHT("foo bar")')).toMatchObject({error: null, result: 'r'});
expect(parser.parse('RIGHT("foo bar", 4)')).toMatchObject({error: null, result: ' bar'});
it("RIGHT", () => {
expect(parser.parse("RIGHT()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('RIGHT("foo bar")')).toMatchObject({
error: null,
result: "r",
});
expect(parser.parse('RIGHT("foo bar", 4)')).toMatchObject({
error: null,
result: " bar",
});
});
it('SEARCH', () => {
expect(parser.parse('SEARCH()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SEARCH("bar")')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('SEARCH("bar", "foo bar")')).toMatchObject({error: null, result: 5});
it("SEARCH", () => {
expect(parser.parse("SEARCH()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('SEARCH("bar")')).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('SEARCH("bar", "foo bar")')).toMatchObject({
error: null,
result: 5,
});
});
it('SPLIT', () => {
expect(parser.parse('SPLIT()')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse('SPLIT("foo bar baz")')).toMatchObject({error: null, result: ['foo bar baz']});
expect(parser.parse('SPLIT("foo bar baz", " ")')).toMatchObject({error: null, result: ['foo', 'bar', 'baz']});
it("SPLIT", () => {
expect(parser.parse("SPLIT()")).toMatchObject({
error: "#ERROR!",
result: null,
});
expect(parser.parse('SPLIT("foo bar baz")')).toMatchObject({
error: null,
result: ["foo bar baz"],
});
expect(parser.parse('SPLIT("foo bar baz", " ")')).toMatchObject({
error: null,
result: ["foo", "bar", "baz"],
});
});
it('SUBSTITUTE', () => {
expect(parser.parse('SUBSTITUTE()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('SUBSTITUTE("foo bar baz")')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('SUBSTITUTE("foo bar baz", "a", "A")')).toMatchObject({error: null, result: 'foo bAr bAz'});
it("SUBSTITUTE", () => {
expect(parser.parse("SUBSTITUTE()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('SUBSTITUTE("foo bar baz")')).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('SUBSTITUTE("foo bar baz", "a", "A")')).toMatchObject({
error: null,
result: "foo bAr bAz",
});
});
it('T', () => {
expect(parser.parse('T()')).toMatchObject({error: null, result: ''});
expect(parser.parse('T(TRUE)')).toMatchObject({error: null, result: ''});
expect(parser.parse('T(9.887)')).toMatchObject({error: null, result: ''});
expect(parser.parse('T("foo bar baz")')).toMatchObject({error: null, result: 'foo bar baz'});
it("T", () => {
expect(parser.parse("T()")).toMatchObject({ error: null, result: "" });
expect(parser.parse("T(TRUE)")).toMatchObject({ error: null, result: "" });
expect(parser.parse("T(9.887)")).toMatchObject({ error: null, result: "" });
expect(parser.parse('T("foo bar baz")')).toMatchObject({
error: null,
result: "foo bar baz",
});
});
xit('TEXT', () => {
expect(parser.parse('TEXT()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('TEXT(1234.99)')).toMatchObject({error: null, result: '1,235'});
expect(parser.parse('TEXT(1234.99, "####.#")')).toMatchObject({error: null, result: '1235.0'});
expect(parser.parse('TEXT(1234.99, "####.###")')).toMatchObject({error: null, result: '1234.990'});
xit("TEXT", () => {
expect(parser.parse("TEXT()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse("TEXT(1234.99)")).toMatchObject({
error: null,
result: "1,235",
});
expect(parser.parse('TEXT(1234.99, "####.#")')).toMatchObject({
error: null,
result: "1235.0",
});
expect(parser.parse('TEXT(1234.99, "####.###")')).toMatchObject({
error: null,
result: "1234.990",
});
});
it('TRIM', () => {
expect(parser.parse('TRIM()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('TRIM("")')).toMatchObject({error: null, result: ''});
expect(parser.parse('TRIM(" ")')).toMatchObject({error: null, result: ''});
expect(parser.parse('TRIM(" foo ")')).toMatchObject({error: null, result: 'foo'});
it("TRIM", () => {
expect(parser.parse("TRIM()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('TRIM("")')).toMatchObject({ error: null, result: "" });
expect(parser.parse('TRIM(" ")')).toMatchObject({
error: null,
result: "",
});
expect(parser.parse('TRIM(" foo ")')).toMatchObject({
error: null,
result: "foo",
});
});
it('UNICHAR', () => {
expect(parser.parse('UNICHAR()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('UNICHAR(33)')).toMatchObject({error: null, result: '!'});
it("UNICHAR", () => {
expect(parser.parse("UNICHAR()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse("UNICHAR(33)")).toMatchObject({
error: null,
result: "!",
});
});
it('UNICODE', () => {
expect(parser.parse('UNICODE()')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse('UNICODE("!")')).toMatchObject({error: null, result: 33});
it("UNICODE", () => {
expect(parser.parse("UNICODE()")).toMatchObject({
error: "#N/A",
result: null,
});
expect(parser.parse('UNICODE("!")')).toMatchObject({
error: null,
result: 33,
});
});
it('UPPER', () => {
expect(parser.parse('UPPER()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('UPPER("foo Bar")')).toMatchObject({error: null, result: 'FOO BAR'});
it("UPPER", () => {
expect(parser.parse("UPPER()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('UPPER("foo Bar")')).toMatchObject({
error: null,
result: "FOO BAR",
});
});
xit('VALUE', () => {
expect(parser.parse('VALUE()')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse('VALUE("$1,000")')).toMatchObject({error: null, result: 1000});
expect(parser.parse('VALUE("01:00:00")')).toMatchObject({error: null, result: 3600});
expect(parser.parse('VALUE("foo Bar")')).toMatchObject({error: null, result: 0});
xit("VALUE", () => {
expect(parser.parse("VALUE()")).toMatchObject({
error: "#VALUE!",
result: null,
});
expect(parser.parse('VALUE("$1,000")')).toMatchObject({
error: null,
result: 1000,
});
expect(parser.parse('VALUE("01:00:00")')).toMatchObject({
error: null,
result: 3600,
});
expect(parser.parse('VALUE("foo Bar")')).toMatchObject({
error: null,
result: 0,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() custom function', () => {
describe(".parse() custom function", () => {
let parser;
beforeEach(() => {
@ -10,24 +10,36 @@ describe('.parse() custom function', () => {
parser = null;
});
it('should evaluate custom functions', () => {
expect(parser.parse('foo()')).toMatchObject({error: '#NAME?', result: null});
it("should evaluate custom functions", () => {
expect(parser.parse("foo()")).toMatchObject({
error: "#NAME?",
result: null,
});
parser.setFunction('ADD_5', (params) => params[0] + 5);
parser.setFunction('GET_LETTER', (params) => {
parser.setFunction("ADD_5", (params) => params[0] + 5);
parser.setFunction("GET_LETTER", (params) => {
const string = params[0];
const index = params[1] - 1;
return string.charAt(index);
});
expect(parser.parse('SUM(4, ADD_5(1))')).toMatchObject({error: null, result: 10});
expect(parser.parse('GET_LETTER("Some string", 3)')).toMatchObject({error: null, result: 'm'});
expect(parser.parse("SUM(4, ADD_5(1))")).toMatchObject({
error: null,
result: 10,
});
expect(parser.parse('GET_LETTER("Some string", 3)')).toMatchObject({
error: null,
result: "m",
});
});
it('should evaluate function with arguments passed as an stringified array', () => {
expect(parser.parse('SUM([])')).toMatchObject({error: null, result: 0});
expect(parser.parse('SUM([1])')).toMatchObject({error: null, result: 1});
expect(parser.parse('SUM([1,2,3])')).toMatchObject({error: null, result: 6});
it("should evaluate function with arguments passed as an stringified array", () => {
expect(parser.parse("SUM([])")).toMatchObject({ error: null, result: 0 });
expect(parser.parse("SUM([1])")).toMatchObject({ error: null, result: 1 });
expect(parser.parse("SUM([1,2,3])")).toMatchObject({
error: null,
result: 6,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() general', () => {
describe(".parse() general", () => {
let parser;
beforeEach(() => {
@ -10,34 +10,52 @@ describe('.parse() general', () => {
parser = null;
});
it('should parse an empty string as it is', () => {
expect(parser.parse('')).toMatchObject({error: null, result: ''});
it("should parse an empty string as it is", () => {
expect(parser.parse("")).toMatchObject({ error: null, result: "" });
});
it('should not parse an number type data', () => {
expect(parser.parse(200)).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse(20.1)).toMatchObject({error: '#ERROR!', result: null});
it("should not parse an number type data", () => {
expect(parser.parse(200)).toMatchObject({ error: "#ERROR!", result: null });
expect(parser.parse(20.1)).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should not parse null type data', () => {
expect(parser.parse(null)).toMatchObject({error: '#ERROR!', result: null});
it("should not parse null type data", () => {
expect(parser.parse(null)).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should not parse undefined type data', () => {
expect(parser.parse(void 0)).toMatchObject({error: '#ERROR!', result: null});
it("should not parse undefined type data", () => {
expect(parser.parse(void 0)).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should not parse object type data', () => {
expect(parser.parse({})).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse({a: 1})).toMatchObject({error: '#ERROR!', result: null});
it("should not parse object type data", () => {
expect(parser.parse({})).toMatchObject({ error: "#ERROR!", result: null });
expect(parser.parse({ a: 1 })).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should not parse array type data', () => {
expect(parser.parse([])).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse([1, 2])).toMatchObject({error: '#ERROR!', result: null});
it("should not parse array type data", () => {
expect(parser.parse([])).toMatchObject({ error: "#ERROR!", result: null });
expect(parser.parse([1, 2])).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should not parse array type data', () => {
expect(parser.parse(() => {})).toMatchObject({error: '#ERROR!', result: null});
it("should not parse array type data", () => {
expect(parser.parse(() => {})).toMatchObject({
error: "#ERROR!",
result: null,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() logical', () => {
describe(".parse() logical", () => {
let parser;
beforeEach(() => {
@ -10,60 +10,159 @@ describe('.parse() logical', () => {
parser = null;
});
it('operator: =', () => {
expect(parser.parse('10 = 10')).toMatchObject({error: null, result: true});
it("operator: =", () => {
expect(parser.parse("10 = 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('10 = 11')).toMatchObject({error: null, result: false});
expect(parser.parse("10 = 11")).toMatchObject({
error: null,
result: false,
});
});
it('operator: >', () => {
expect(parser.parse('11 > 10')).toMatchObject({error: null, result: true});
expect(parser.parse('10 > 1.1')).toMatchObject({error: null, result: true});
expect(parser.parse('10 >- 10')).toMatchObject({error: null, result: true});
it("operator: >", () => {
expect(parser.parse("11 > 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("10 > 1.1")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("10 >- 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('10 > 11')).toMatchObject({error: null, result: false});
expect(parser.parse('10 > 11.1')).toMatchObject({error: null, result: false});
expect(parser.parse('10 > 10.00001')).toMatchObject({error: null, result: false});
expect(parser.parse("10 > 11")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10 > 11.1")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10 > 10.00001")).toMatchObject({
error: null,
result: false,
});
});
it('operator: <', () => {
expect(parser.parse('10 < 11')).toMatchObject({error: null, result: true});
expect(parser.parse('10 < 11.1')).toMatchObject({error: null, result: true});
expect(parser.parse('10 < 10.00001')).toMatchObject({error: null, result: true});
it("operator: <", () => {
expect(parser.parse("10 < 11")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("10 < 11.1")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("10 < 10.00001")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('11 < 10')).toMatchObject({error: null, result: false});
expect(parser.parse('10 < 1.1')).toMatchObject({error: null, result: false});
expect(parser.parse('10 <- 10')).toMatchObject({error: null, result: false});
expect(parser.parse("11 < 10")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10 < 1.1")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10 <- 10")).toMatchObject({
error: null,
result: false,
});
});
it('operator: >=', () => {
expect(parser.parse('11 >= 10')).toMatchObject({error: null, result: true});
expect(parser.parse('11 >= 11')).toMatchObject({error: null, result: true});
expect(parser.parse('10 >= 10')).toMatchObject({error: null, result: true});
expect(parser.parse('10 >= -10')).toMatchObject({error: null, result: true});
it("operator: >=", () => {
expect(parser.parse("11 >= 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("11 >= 11")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("10 >= 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("10 >= -10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('10 >= 11')).toMatchObject({error: null, result: false});
expect(parser.parse('10 >= 11.1')).toMatchObject({error: null, result: false});
expect(parser.parse('10 >= 10.00001')).toMatchObject({error: null, result: false});
expect(parser.parse("10 >= 11")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10 >= 11.1")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10 >= 10.00001")).toMatchObject({
error: null,
result: false,
});
});
it('operator: <=', () => {
expect(parser.parse('10 <= 10')).toMatchObject({error: null, result: true});
expect(parser.parse('1.1 <= 10')).toMatchObject({error: null, result: true});
expect(parser.parse('-10 <= 10')).toMatchObject({error: null, result: true});
it("operator: <=", () => {
expect(parser.parse("10 <= 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("1.1 <= 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("-10 <= 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('11 <= 10')).toMatchObject({error: null, result: false});
expect(parser.parse('11.1 <= 10')).toMatchObject({error: null, result: false});
expect(parser.parse('10.00001 <= 10')).toMatchObject({error: null, result: false});
expect(parser.parse("11 <= 10")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("11.1 <= 10")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10.00001 <= 10")).toMatchObject({
error: null,
result: false,
});
});
it('operator: <>', () => {
expect(parser.parse('10 <> 11')).toMatchObject({error: null, result: true});
expect(parser.parse('1.1 <> 10')).toMatchObject({error: null, result: true});
expect(parser.parse('-10 <> 10')).toMatchObject({error: null, result: true});
it("operator: <>", () => {
expect(parser.parse("10 <> 11")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("1.1 <> 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse("-10 <> 10")).toMatchObject({
error: null,
result: true,
});
expect(parser.parse('10 <> 10')).toMatchObject({error: null, result: false});
expect(parser.parse('11.1 <> 11.1')).toMatchObject({error: null, result: false});
expect(parser.parse('10.00001 <> 10.00001')).toMatchObject({error: null, result: false});
expect(parser.parse("10 <> 10")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("11.1 <> 11.1")).toMatchObject({
error: null,
result: false,
});
expect(parser.parse("10.00001 <> 10.00001")).toMatchObject({
error: null,
result: false,
});
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() math', () => {
describe(".parse() math", () => {
let parser;
beforeEach(() => {
@ -10,53 +10,111 @@ describe('.parse() math', () => {
parser = null;
});
it('operator: +', () => {
expect(parser.parse('10+10')).toMatchObject({error: null, result: 20});
expect(parser.parse('10 + 10')).toMatchObject({error: null, result: 20});
expect(parser.parse('10 + 11 + 23 + 11 + 2')).toMatchObject({error: null, result: 57});
expect(parser.parse('1.4425 + 4.333')).toMatchObject({error: null, result: 5.7755});
expect(parser.parse('"foo" + 4.333')).toMatchObject({error: '#VALUE!', result: null});
it("operator: +", () => {
expect(parser.parse("10+10")).toMatchObject({ error: null, result: 20 });
expect(parser.parse("10 + 10")).toMatchObject({ error: null, result: 20 });
expect(parser.parse("10 + 11 + 23 + 11 + 2")).toMatchObject({
error: null,
result: 57,
});
expect(parser.parse("1.4425 + 4.333")).toMatchObject({
error: null,
result: 5.7755,
});
expect(parser.parse('"foo" + 4.333')).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('operator: -', () => {
expect(parser.parse('10-10')).toMatchObject({error: null, result: 0});
expect(parser.parse('10 - 10')).toMatchObject({error: null, result: 0});
expect(parser.parse('10 - 10 - 2')).toMatchObject({error: null, result: -2});
expect(parser.parse('10 - 11 - 23 - 11 - 2')).toMatchObject({error: null, result: -37});
expect(parser.parse('"foo" - 4.333')).toMatchObject({error: '#VALUE!', result: null});
it("operator: -", () => {
expect(parser.parse("10-10")).toMatchObject({ error: null, result: 0 });
expect(parser.parse("10 - 10")).toMatchObject({ error: null, result: 0 });
expect(parser.parse("10 - 10 - 2")).toMatchObject({
error: null,
result: -2,
});
expect(parser.parse("10 - 11 - 23 - 11 - 2")).toMatchObject({
error: null,
result: -37,
});
expect(parser.parse('"foo" - 4.333')).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('operator: /', () => {
expect(parser.parse('2 / 1')).toMatchObject({error: null, result: 2});
expect(parser.parse('64 / 2 / 4')).toMatchObject({error: null, result: 8});
expect(parser.parse('2 / 0')).toMatchObject({error: '#DIV/0!', result: null});
expect(parser.parse('"foo" / 4.333')).toMatchObject({error: '#VALUE!', result: null});
it("operator: /", () => {
expect(parser.parse("2 / 1")).toMatchObject({ error: null, result: 2 });
expect(parser.parse("64 / 2 / 4")).toMatchObject({
error: null,
result: 8,
});
expect(parser.parse("2 / 0")).toMatchObject({
error: "#DIV/0!",
result: null,
});
expect(parser.parse('"foo" / 4.333')).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('operator: *', () => {
expect(parser.parse('0 * 0 * 0 * 0 * 0')).toMatchObject({error: null, result: 0});
expect(parser.parse('2 * 1')).toMatchObject({error: null, result: 2});
expect(parser.parse('64 * 2 * 4')).toMatchObject({error: null, result: 512});
expect(parser.parse('"foo" * 4.333')).toMatchObject({error: '#VALUE!', result: null});
it("operator: *", () => {
expect(parser.parse("0 * 0 * 0 * 0 * 0")).toMatchObject({
error: null,
result: 0,
});
expect(parser.parse("2 * 1")).toMatchObject({ error: null, result: 2 });
expect(parser.parse("64 * 2 * 4")).toMatchObject({
error: null,
result: 512,
});
expect(parser.parse('"foo" * 4.333')).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('operator: ^', () => {
expect(parser.parse('2 ^ 5')).toMatchObject({error: null, result: 32});
expect(parser.parse('"foo" ^ 4')).toMatchObject({error: '#VALUE!', result: null});
it("operator: ^", () => {
expect(parser.parse("2 ^ 5")).toMatchObject({ error: null, result: 32 });
expect(parser.parse('"foo" ^ 4')).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('operator: &', () => {
expect(parser.parse('2 & 5')).toMatchObject({error: null, result: '25'});
expect(parser.parse('(2 & 5)')).toMatchObject({error: null, result: '25'});
expect(parser.parse('("" & "")')).toMatchObject({error: null, result: ''});
expect(parser.parse('"" & ""')).toMatchObject({error: null, result: ''});
expect(parser.parse('("Hello" & " world") & "!"')).toMatchObject({error: null, result: 'Hello world!'});
it("operator: &", () => {
expect(parser.parse("2 & 5")).toMatchObject({ error: null, result: "25" });
expect(parser.parse("(2 & 5)")).toMatchObject({
error: null,
result: "25",
});
expect(parser.parse('("" & "")')).toMatchObject({
error: null,
result: "",
});
expect(parser.parse('"" & ""')).toMatchObject({ error: null, result: "" });
expect(parser.parse('("Hello" & " world") & "!"')).toMatchObject({
error: null,
result: "Hello world!",
});
});
it('mixed operators', () => {
expect(parser.parse('1 + 10 - 20 * 3/2')).toMatchObject({error: null, result: -19});
expect(parser.parse('((1 + 10 - 20 * 3 / 2) + 20) * 10')).toMatchObject({error: null, result: 10});
expect(parser.parse('(((1 + 10 - 20 * 3/2) + 20) * 10) / 5.12')).toMatchObject({error: null, result: 1.953125});
expect(parser.parse('(((1 + "foo" - 20 * 3/2) + 20) * 10) / 5.12')).toMatchObject({error: '#VALUE!', result: null});
it("mixed operators", () => {
expect(parser.parse("1 + 10 - 20 * 3/2")).toMatchObject({
error: null,
result: -19,
});
expect(parser.parse("((1 + 10 - 20 * 3 / 2) + 20) * 10")).toMatchObject({
error: null,
result: 10,
});
expect(
parser.parse("(((1 + 10 - 20 * 3/2) + 20) * 10) / 5.12")
).toMatchObject({ error: null, result: 1.953125 });
expect(
parser.parse('(((1 + "foo" - 20 * 3/2) + 20) * 10) / 5.12')
).toMatchObject({ error: "#VALUE!", result: null });
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../../src/parser';
import Parser from "../../../src/parser";
describe('.parse() variable', () => {
describe(".parse() variable", () => {
let parser;
beforeEach(() => {
@ -10,19 +10,25 @@ describe('.parse() variable', () => {
parser = null;
});
it('should evaluate defaults variables', () => {
expect(parser.parse('TRUE')).toMatchObject({error: null, result: true});
expect(parser.parse('FALSE')).toMatchObject({error: null, result: false});
expect(parser.parse('NULL')).toMatchObject({error: null, result: null});
it("should evaluate defaults variables", () => {
expect(parser.parse("TRUE")).toMatchObject({ error: null, result: true });
expect(parser.parse("FALSE")).toMatchObject({ error: null, result: false });
expect(parser.parse("NULL")).toMatchObject({ error: null, result: null });
});
it('should evaluate custom variables', () => {
expect(parser.parse('foo')).toMatchObject({error: '#NAME?', result: null});
it("should evaluate custom variables", () => {
expect(parser.parse("foo")).toMatchObject({
error: "#NAME?",
result: null,
});
parser.setVariable('foo', 'bar');
parser.setVariable('baz', '6.6');
parser.setVariable("foo", "bar");
parser.setVariable("baz", "6.6");
expect(parser.parse('foo')).toMatchObject({error: null, result: 'bar'});
expect(parser.parse('SUM(baz, 2.1, 0.2)')).toMatchObject({error: null, result: 8.899999999999999});
expect(parser.parse("foo")).toMatchObject({ error: null, result: "bar" });
expect(parser.parse("SUM(baz, 2.1, 0.2)")).toMatchObject({
error: null,
result: 8.899999999999999,
});
});
});

View File

@ -1,151 +1,151 @@
import error, {isValidStrict} from '../../src/error';
import error, { isValidStrict } from "../../src/error";
describe('.error()', () => {
it('should return null for unrecognized error types', () => {
describe(".error()", () => {
it("should return null for unrecognized error types", () => {
expect(error()).toBe(null);
expect(error('')).toBe(null);
expect(error('dewdewdw')).toBe(null);
expect(error('ERROR1')).toBe(null);
expect(error(' ERROR!')).toBe(null);
expect(error(' #ERROR!')).toBe(null);
expect(error("")).toBe(null);
expect(error("dewdewdw")).toBe(null);
expect(error("ERROR1")).toBe(null);
expect(error(" ERROR!")).toBe(null);
expect(error(" #ERROR!")).toBe(null);
});
it('should return `#ERROR!`', () => {
expect(error('ERROR')).toBe('#ERROR!');
expect(error('ERROR!')).toBe('#ERROR!');
expect(error('#ERROR')).toBe('#ERROR!');
expect(error('#ERROR!')).toBe('#ERROR!');
expect(error('#ERROR?')).toBe('#ERROR!');
it("should return `#ERROR!`", () => {
expect(error("ERROR")).toBe("#ERROR!");
expect(error("ERROR!")).toBe("#ERROR!");
expect(error("#ERROR")).toBe("#ERROR!");
expect(error("#ERROR!")).toBe("#ERROR!");
expect(error("#ERROR?")).toBe("#ERROR!");
});
it('should return `#DIV/0!`', () => {
expect(error('DIV/0')).toBe('#DIV/0!');
expect(error('DIV/0!')).toBe('#DIV/0!');
expect(error('#DIV/0')).toBe('#DIV/0!');
expect(error('#DIV/0!')).toBe('#DIV/0!');
expect(error('#DIV/0?')).toBe('#DIV/0!');
it("should return `#DIV/0!`", () => {
expect(error("DIV/0")).toBe("#DIV/0!");
expect(error("DIV/0!")).toBe("#DIV/0!");
expect(error("#DIV/0")).toBe("#DIV/0!");
expect(error("#DIV/0!")).toBe("#DIV/0!");
expect(error("#DIV/0?")).toBe("#DIV/0!");
});
it('should return `#NAME?`', () => {
expect(error('NAME')).toBe('#NAME?');
expect(error('NAME!')).toBe('#NAME?');
expect(error('#NAME')).toBe('#NAME?');
expect(error('#NAME!')).toBe('#NAME?');
expect(error('#NAME?')).toBe('#NAME?');
it("should return `#NAME?`", () => {
expect(error("NAME")).toBe("#NAME?");
expect(error("NAME!")).toBe("#NAME?");
expect(error("#NAME")).toBe("#NAME?");
expect(error("#NAME!")).toBe("#NAME?");
expect(error("#NAME?")).toBe("#NAME?");
});
it('should return `#N/A`', () => {
expect(error('N/A')).toBe('#N/A');
expect(error('N/A!')).toBe('#N/A');
expect(error('#N/A')).toBe('#N/A');
expect(error('#N/A!')).toBe('#N/A');
expect(error('#N/A?')).toBe('#N/A');
it("should return `#N/A`", () => {
expect(error("N/A")).toBe("#N/A");
expect(error("N/A!")).toBe("#N/A");
expect(error("#N/A")).toBe("#N/A");
expect(error("#N/A!")).toBe("#N/A");
expect(error("#N/A?")).toBe("#N/A");
});
it('should return `#NULL!`', () => {
expect(error('NULL')).toBe('#NULL!');
expect(error('NULL!')).toBe('#NULL!');
expect(error('#NULL')).toBe('#NULL!');
expect(error('#NULL!')).toBe('#NULL!');
expect(error('#NULL?')).toBe('#NULL!');
it("should return `#NULL!`", () => {
expect(error("NULL")).toBe("#NULL!");
expect(error("NULL!")).toBe("#NULL!");
expect(error("#NULL")).toBe("#NULL!");
expect(error("#NULL!")).toBe("#NULL!");
expect(error("#NULL?")).toBe("#NULL!");
});
it('should return `#NUM!`', () => {
expect(error('NUM')).toBe('#NUM!');
expect(error('NUM!')).toBe('#NUM!');
expect(error('#NUM')).toBe('#NUM!');
expect(error('#NUM!')).toBe('#NUM!');
expect(error('#NUM?')).toBe('#NUM!');
it("should return `#NUM!`", () => {
expect(error("NUM")).toBe("#NUM!");
expect(error("NUM!")).toBe("#NUM!");
expect(error("#NUM")).toBe("#NUM!");
expect(error("#NUM!")).toBe("#NUM!");
expect(error("#NUM?")).toBe("#NUM!");
});
it('should return `#REF!`', () => {
expect(error('REF')).toBe('#REF!');
expect(error('REF!')).toBe('#REF!');
expect(error('#REF')).toBe('#REF!');
expect(error('#REF!')).toBe('#REF!');
expect(error('#REF?')).toBe('#REF!');
it("should return `#REF!`", () => {
expect(error("REF")).toBe("#REF!");
expect(error("REF!")).toBe("#REF!");
expect(error("#REF")).toBe("#REF!");
expect(error("#REF!")).toBe("#REF!");
expect(error("#REF?")).toBe("#REF!");
});
it('should return `#VALUE?`', () => {
expect(error('VALUE')).toBe('#VALUE!');
expect(error('VALUE!')).toBe('#VALUE!');
expect(error('#VALUE')).toBe('#VALUE!');
expect(error('#VALUE!')).toBe('#VALUE!');
expect(error('#VALUE?')).toBe('#VALUE!');
it("should return `#VALUE?`", () => {
expect(error("VALUE")).toBe("#VALUE!");
expect(error("VALUE!")).toBe("#VALUE!");
expect(error("#VALUE")).toBe("#VALUE!");
expect(error("#VALUE!")).toBe("#VALUE!");
expect(error("#VALUE?")).toBe("#VALUE!");
});
});
describe('.isValidStrict()', () => {
it('should return false for unrecognized error types', () => {
describe(".isValidStrict()", () => {
it("should return false for unrecognized error types", () => {
expect(isValidStrict()).toBeFalsy();
expect(isValidStrict('')).toBeFalsy();
expect(isValidStrict('dewdewdw')).toBeFalsy();
expect(isValidStrict('ERROR1')).toBeFalsy();
expect(isValidStrict(' ERROR!')).toBeFalsy();
expect(isValidStrict(' #ERROR!')).toBeFalsy();
expect(isValidStrict("")).toBeFalsy();
expect(isValidStrict("dewdewdw")).toBeFalsy();
expect(isValidStrict("ERROR1")).toBeFalsy();
expect(isValidStrict(" ERROR!")).toBeFalsy();
expect(isValidStrict(" #ERROR!")).toBeFalsy();
});
it('should return true for valid general error (`#ERROR!`)', () => {
expect(isValidStrict('#ERROR!')).toBeTruthy();
expect(isValidStrict('ERROR')).toBeFalsy();
expect(isValidStrict('ERROR!')).toBeFalsy();
expect(isValidStrict('#ERROR')).toBeFalsy();
expect(isValidStrict('#ERROR?')).toBeFalsy();
it("should return true for valid general error (`#ERROR!`)", () => {
expect(isValidStrict("#ERROR!")).toBeTruthy();
expect(isValidStrict("ERROR")).toBeFalsy();
expect(isValidStrict("ERROR!")).toBeFalsy();
expect(isValidStrict("#ERROR")).toBeFalsy();
expect(isValidStrict("#ERROR?")).toBeFalsy();
});
it('should return true for valid `#DIV/0!` error', () => {
expect(isValidStrict('#DIV/0!')).toBeTruthy();
expect(isValidStrict('DIV/0')).toBeFalsy();
expect(isValidStrict('DIV/0!')).toBeFalsy();
expect(isValidStrict('#DIV/0')).toBeFalsy();
expect(isValidStrict('#DIV/0?')).toBeFalsy();
it("should return true for valid `#DIV/0!` error", () => {
expect(isValidStrict("#DIV/0!")).toBeTruthy();
expect(isValidStrict("DIV/0")).toBeFalsy();
expect(isValidStrict("DIV/0!")).toBeFalsy();
expect(isValidStrict("#DIV/0")).toBeFalsy();
expect(isValidStrict("#DIV/0?")).toBeFalsy();
});
it('should return true for valid `#NAME?` error', () => {
expect(isValidStrict('#NAME?')).toBeTruthy();
expect(isValidStrict('NAME')).toBeFalsy();
expect(isValidStrict('NAME!')).toBeFalsy();
expect(isValidStrict('#NAME')).toBeFalsy();
expect(isValidStrict('#NAME!')).toBeFalsy();
it("should return true for valid `#NAME?` error", () => {
expect(isValidStrict("#NAME?")).toBeTruthy();
expect(isValidStrict("NAME")).toBeFalsy();
expect(isValidStrict("NAME!")).toBeFalsy();
expect(isValidStrict("#NAME")).toBeFalsy();
expect(isValidStrict("#NAME!")).toBeFalsy();
});
it('should return true for valid `#N/A` error', () => {
expect(isValidStrict('#N/A')).toBeTruthy();
expect(isValidStrict('N/A')).toBeFalsy();
expect(isValidStrict('N/A!')).toBeFalsy();
expect(isValidStrict('#N/A!')).toBeFalsy();
expect(isValidStrict('#N/A?')).toBeFalsy();
it("should return true for valid `#N/A` error", () => {
expect(isValidStrict("#N/A")).toBeTruthy();
expect(isValidStrict("N/A")).toBeFalsy();
expect(isValidStrict("N/A!")).toBeFalsy();
expect(isValidStrict("#N/A!")).toBeFalsy();
expect(isValidStrict("#N/A?")).toBeFalsy();
});
it('should return true for valid `#NULL!` error', () => {
expect(isValidStrict('#NULL!')).toBeTruthy();
expect(isValidStrict('NULL')).toBeFalsy();
expect(isValidStrict('NULL!')).toBeFalsy();
expect(isValidStrict('#NULL')).toBeFalsy();
expect(isValidStrict('#NULL?')).toBeFalsy();
it("should return true for valid `#NULL!` error", () => {
expect(isValidStrict("#NULL!")).toBeTruthy();
expect(isValidStrict("NULL")).toBeFalsy();
expect(isValidStrict("NULL!")).toBeFalsy();
expect(isValidStrict("#NULL")).toBeFalsy();
expect(isValidStrict("#NULL?")).toBeFalsy();
});
it('should return true for valid `#NUM!` error', () => {
expect(isValidStrict('#NUM!')).toBeTruthy();
expect(isValidStrict('NUM')).toBeFalsy();
expect(isValidStrict('NUM!')).toBeFalsy();
expect(isValidStrict('#NUM')).toBeFalsy();
expect(isValidStrict('#NUM?')).toBeFalsy();
it("should return true for valid `#NUM!` error", () => {
expect(isValidStrict("#NUM!")).toBeTruthy();
expect(isValidStrict("NUM")).toBeFalsy();
expect(isValidStrict("NUM!")).toBeFalsy();
expect(isValidStrict("#NUM")).toBeFalsy();
expect(isValidStrict("#NUM?")).toBeFalsy();
});
it('should return true for valid `#REF!` error', () => {
expect(isValidStrict('#REF!')).toBeTruthy();
expect(isValidStrict('REF')).toBeFalsy();
expect(isValidStrict('REF!')).toBeFalsy();
expect(isValidStrict('#REF')).toBeFalsy();
expect(isValidStrict('#REF?')).toBeFalsy();
it("should return true for valid `#REF!` error", () => {
expect(isValidStrict("#REF!")).toBeTruthy();
expect(isValidStrict("REF")).toBeFalsy();
expect(isValidStrict("REF!")).toBeFalsy();
expect(isValidStrict("#REF")).toBeFalsy();
expect(isValidStrict("#REF?")).toBeFalsy();
});
it('should return true for valid `#VALUE!` error', () => {
expect(isValidStrict('#VALUE!')).toBeTruthy();
expect(isValidStrict('VALUE')).toBeFalsy();
expect(isValidStrict('VALUE!')).toBeFalsy();
expect(isValidStrict('#VALUE')).toBeFalsy();
expect(isValidStrict('#VALUE?')).toBeFalsy();
it("should return true for valid `#VALUE!` error", () => {
expect(isValidStrict("#VALUE!")).toBeTruthy();
expect(isValidStrict("VALUE")).toBeFalsy();
expect(isValidStrict("VALUE!")).toBeFalsy();
expect(isValidStrict("#VALUE")).toBeFalsy();
expect(isValidStrict("#VALUE?")).toBeFalsy();
});
});

View File

@ -1,99 +1,101 @@
import evaluateByOperator, {registerOperation} from '../../../src/evaluate-by-operator/evaluate-by-operator';
import evaluateByOperator, {
registerOperation,
} from "../../../src/evaluate-by-operator/evaluate-by-operator";
describe('.registerOperation()', () => {
it('should register new operator and evaluate it', () => {
registerOperation('foo', (a, b) => a + b);
describe(".registerOperation()", () => {
it("should register new operator and evaluate it", () => {
registerOperation("foo", (a, b) => a + b);
expect(evaluateByOperator('foo', [2, 8.8])).toBe(10.8);
expect(evaluateByOperator('foo', ['2', '8.8'])).toBe('28.8');
expect(evaluateByOperator("foo", [2, 8.8])).toBe(10.8);
expect(evaluateByOperator("foo", ["2", "8.8"])).toBe("28.8");
});
});
describe('.evaluateByOperator()', () => {
it('should throw exception when operator do not exist', () => {
describe(".evaluateByOperator()", () => {
it("should throw exception when operator do not exist", () => {
expect(() => {
evaluateByOperator('bar', [2, 8.8]);
}).toThrow('NAME');
evaluateByOperator("bar", [2, 8.8]);
}).toThrow("NAME");
expect(() => {
evaluateByOperator('baz');
}).toThrow('NAME');
evaluateByOperator("baz");
}).toThrow("NAME");
});
it('should not to throw exception for `add` operator', () => {
it("should not to throw exception for `add` operator", () => {
expect(() => {
evaluateByOperator('+', [2, 8.8]);
evaluateByOperator("+", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `ampersand` operator', () => {
it("should not to throw exception for `ampersand` operator", () => {
expect(() => {
evaluateByOperator('&', [2, 8.8]);
evaluateByOperator("&", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `divide` operator', () => {
it("should not to throw exception for `divide` operator", () => {
expect(() => {
evaluateByOperator('/', [2, 8.8]);
evaluateByOperator("/", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `equal` operator', () => {
it("should not to throw exception for `equal` operator", () => {
expect(() => {
evaluateByOperator('=', [2, 8.8]);
evaluateByOperator("=", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `formula function` operator', () => {
it("should not to throw exception for `formula function` operator", () => {
expect(() => {
evaluateByOperator('SUM', [2, 8.8]);
evaluateByOperator("SUM", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `greater than` operator', () => {
it("should not to throw exception for `greater than` operator", () => {
expect(() => {
evaluateByOperator('>', [2, 8.8]);
evaluateByOperator(">", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `greater than or equal` operator', () => {
it("should not to throw exception for `greater than or equal` operator", () => {
expect(() => {
evaluateByOperator('>=', [2, 8.8]);
evaluateByOperator(">=", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `less than` operator', () => {
it("should not to throw exception for `less than` operator", () => {
expect(() => {
evaluateByOperator('<', [2, 8.8]);
evaluateByOperator("<", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `less than or equal` operator', () => {
it("should not to throw exception for `less than or equal` operator", () => {
expect(() => {
evaluateByOperator('<=', [2, 8.8]);
evaluateByOperator("<=", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `minus` operator', () => {
it("should not to throw exception for `minus` operator", () => {
expect(() => {
evaluateByOperator('-', [2, 8.8]);
evaluateByOperator("-", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `multiply` operator', () => {
it("should not to throw exception for `multiply` operator", () => {
expect(() => {
evaluateByOperator('*', [2, 8.8]);
evaluateByOperator("*", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `not equal` operator', () => {
it("should not to throw exception for `not equal` operator", () => {
expect(() => {
evaluateByOperator('<>', [2, 8.8]);
evaluateByOperator("<>", [2, 8.8]);
}).not.toThrow();
});
it('should not to throw exception for `power` operator', () => {
it("should not to throw exception for `power` operator", () => {
expect(() => {
evaluateByOperator('^', [2, 2]);
evaluateByOperator("^", [2, 2]);
}).not.toThrow();
});
});

View File

@ -1,17 +1,17 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/add';
import func from "../../../../src/evaluate-by-operator/operator/add";
describe('add operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('+');
describe("add operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("+");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(10.8);
expect(func('2', 8.8)).toBe(10.8);
expect(func('2', '8.8')).toBe(10.8);
expect(func('2', '-8.8', 6, 0.4)).toBe(-0.4000000000000007);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(func("2", 8.8)).toBe(10.8);
expect(func("2", "8.8")).toBe(10.8);
expect(func("2", "-8.8", 6, 0.4)).toBe(-0.4000000000000007);
expect(() => func("foo", " ", "bar", " baz")).toThrow("VALUE");
expect(() => func("foo", 2)).toThrow("VALUE");
});
});

View File

@ -1,15 +1,15 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/ampersand';
import func from "../../../../src/evaluate-by-operator/operator/ampersand";
describe('ampersand operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('&');
describe("ampersand operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("&");
});
it('should correctly process values', () => {
expect(func(2, 8.8)).toBe('28.8');
expect(func('2', 8.8)).toBe('28.8');
expect(func('2', '-8.8', 6, 0.4)).toBe('2-8.860.4');
expect(func('foo', ' ', 'bar', ' baz')).toBe('foo bar baz');
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe("28.8");
expect(func("2", 8.8)).toBe("28.8");
expect(func("2", "-8.8", 6, 0.4)).toBe("2-8.860.4");
expect(func("foo", " ", "bar", " baz")).toBe("foo bar baz");
});
});

View File

@ -1,17 +1,17 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/divide';
import func from "../../../../src/evaluate-by-operator/operator/divide";
describe('divide operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('/');
describe("divide operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("/");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(0.22727272727272727);
expect(func('2', 8.8)).toBe(0.22727272727272727);
expect(func('2', '-8.8', 6, 0.4)).toBe(-0.0946969696969697);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(func("2", 8.8)).toBe(0.22727272727272727);
expect(func("2", "-8.8", 6, 0.4)).toBe(-0.0946969696969697);
expect(() => func("foo", " ", "bar", " baz")).toThrow("VALUE");
expect(func(0, 1)).toBe(0);
expect(() => func(1, 0)).toThrow('DIV/0');
expect(() => func(1, 0)).toThrow("DIV/0");
});
});

View File

@ -1,15 +1,15 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/equal';
import func from "../../../../src/evaluate-by-operator/operator/equal";
describe('equal operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('=');
describe("equal operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("=");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(false);
expect(func('2', 8.8)).toBe(false);
expect(func(1, '1')).toBe(false);
expect(func("2", 8.8)).toBe(false);
expect(func(1, "1")).toBe(false);
expect(func(void 0, null)).toBe(false);
expect(func(0, null)).toBe(false);
expect(func(0, void 0)).toBe(false);

View File

@ -1,33 +1,33 @@
/* eslint-disable import/no-named-as-default-member */
import SUPPORTED_FORMULAS from '../../../../src/supported-formulas';
import func from '../../../../src/evaluate-by-operator/operator/formula-function';
import SUPPORTED_FORMULAS from "../../../../src/supported-formulas";
import func from "../../../../src/evaluate-by-operator/operator/formula-function";
describe('formula function operator', () => {
it('should set SYMBOL const', () => {
describe("formula function operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe(SUPPORTED_FORMULAS);
});
it('should set isFactory const', () => {
it("should set isFactory const", () => {
expect(func.isFactory).toBe(true);
});
it('should return error when formula not exist (shallow call)', () => {
expect(() => func('SUMEE')(8.8, 2, 1, 4)).toThrow('NAME');
it("should return error when formula not exist (shallow call)", () => {
expect(() => func("SUMEE")(8.8, 2, 1, 4)).toThrow("NAME");
});
it('should return error when formula not exist (deep call)', () => {
expect(() => func('SUMEE.INT')(8.8, 2, 1, 4)).toThrow('NAME');
it("should return error when formula not exist (deep call)", () => {
expect(() => func("SUMEE.INT")(8.8, 2, 1, 4)).toThrow("NAME");
});
it('should correctly process formula (shallow call)', () => {
const result = func('SUM')(8.8, 2, 1, 4);
it("should correctly process formula (shallow call)", () => {
const result = func("SUM")(8.8, 2, 1, 4);
expect(result).toBe(15.8);
});
it('should correctly process formula passed in lower case', () => {
const result1 = func('Sum')(8.8, 2, 1, 4);
const result2 = func('Rank.eq')(2, [7, 3.5, 3.5, 1, 2]);
it("should correctly process formula passed in lower case", () => {
const result1 = func("Sum")(8.8, 2, 1, 4);
const result2 = func("Rank.eq")(2, [7, 3.5, 3.5, 1, 2]);
expect(result1).toBe(15.8);
expect(result2).toBe(4);

View File

@ -1,19 +1,19 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/greater-than-or-equal';
import func from "../../../../src/evaluate-by-operator/operator/greater-than-or-equal";
describe('greater than or equal operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('>=');
describe("greater than or equal operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe(">=");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(false);
expect(func('2', 8.8)).toBe(false);
expect(func("2", 8.8)).toBe(false);
expect(func(void 0, null)).toBe(false);
expect(func(0, void 0)).toBe(false);
expect(func(0, null)).toBe(true); // JS natively
expect(func(1, '1')).toBe(true);
expect(func(1, "1")).toBe(true);
expect(func(1, 1)).toBe(true);
expect(func(2, 1)).toBe(true);
expect(func(2.2, 2.1)).toBe(true);

View File

@ -1,15 +1,15 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/greater-than';
import func from "../../../../src/evaluate-by-operator/operator/greater-than";
describe('greater than operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('>');
describe("greater than operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe(">");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(false);
expect(func('2', 8.8)).toBe(false);
expect(func(1, '1')).toBe(false);
expect(func("2", 8.8)).toBe(false);
expect(func(1, "1")).toBe(false);
expect(func(1, 1)).toBe(false);
expect(func(void 0, null)).toBe(false);
expect(func(0, null)).toBe(false);

View File

@ -1,21 +1,21 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/less-than-or-equal';
import func from "../../../../src/evaluate-by-operator/operator/less-than-or-equal";
describe('less than or equal operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('<=');
describe("less than or equal operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("<=");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 1)).toBe(false);
expect(func(2.2, 2.1)).toBe(false);
expect(func(void 0, null)).toBe(false);
expect(func(0, void 0)).toBe(false);
expect(func(0, null)).toBe(true); // JS natively
expect(func(1, '1')).toBe(true);
expect(func(1, "1")).toBe(true);
expect(func(1, 1)).toBe(true);
expect(func('2', 8.8)).toBe(true);
expect(func("2", 8.8)).toBe(true);
expect(func(2, 8.8)).toBe(true);
});
});

View File

@ -1,21 +1,21 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/less-than';
import func from "../../../../src/evaluate-by-operator/operator/less-than";
describe('less than operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('<');
describe("less than operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("<");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 1)).toBe(false);
expect(func(2.2, 2.1)).toBe(false);
expect(func(1, '1')).toBe(false);
expect(func(1, "1")).toBe(false);
expect(func(1, 1)).toBe(false);
expect(func(void 0, null)).toBe(false);
expect(func(0, null)).toBe(false);
expect(func(0, void 0)).toBe(false);
expect(func('2', 8.8)).toBe(true);
expect(func("2", 8.8)).toBe(true);
expect(func(2, 8.8)).toBe(true);
});
});

View File

@ -1,17 +1,17 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/minus';
import func from "../../../../src/evaluate-by-operator/operator/minus";
describe('minus operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('-');
describe("minus operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("-");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(-6.800000000000001);
expect(func('2', 8.8)).toBe(-6.800000000000001);
expect(func('2', '8.8')).toBe(-6.800000000000001);
expect(func('2', '-8.8', 6, 0.4)).toBe(4.4);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(func("2", 8.8)).toBe(-6.800000000000001);
expect(func("2", "8.8")).toBe(-6.800000000000001);
expect(func("2", "-8.8", 6, 0.4)).toBe(4.4);
expect(() => func("foo", " ", "bar", " baz")).toThrow("VALUE");
expect(() => func("foo", 2)).toThrow("VALUE");
});
});

View File

@ -1,17 +1,17 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/multiply';
import func from "../../../../src/evaluate-by-operator/operator/multiply";
describe('multiply operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('*');
describe("multiply operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("*");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(17.6);
expect(func('2', 8.8)).toBe(17.6);
expect(func('2', '8.8')).toBe(17.6);
expect(func('2', '-8.8', 6, 0.4)).toBe(-42.24000000000001);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(func("2", 8.8)).toBe(17.6);
expect(func("2", "8.8")).toBe(17.6);
expect(func("2", "-8.8", 6, 0.4)).toBe(-42.24000000000001);
expect(() => func("foo", " ", "bar", " baz")).toThrow("VALUE");
expect(() => func("foo", 2)).toThrow("VALUE");
});
});

View File

@ -1,15 +1,15 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/not-equal';
import func from "../../../../src/evaluate-by-operator/operator/not-equal";
describe('not equal operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('<>');
describe("not equal operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("<>");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(true);
expect(func('2', 8.8)).toBe(true);
expect(func(1, '1')).toBe(true);
expect(func("2", 8.8)).toBe(true);
expect(func(1, "1")).toBe(true);
expect(func(void 0, null)).toBe(true);
expect(func(0, null)).toBe(true);
expect(func(0, void 0)).toBe(true);

View File

@ -1,17 +1,17 @@
/* eslint-disable import/no-named-as-default-member */
import func from '../../../../src/evaluate-by-operator/operator/power';
import func from "../../../../src/evaluate-by-operator/operator/power";
describe('power operator', () => {
it('should set SYMBOL const', () => {
expect(func.SYMBOL).toBe('^');
describe("power operator", () => {
it("should set SYMBOL const", () => {
expect(func.SYMBOL).toBe("^");
});
it('should correctly process values', () => {
it("should correctly process values", () => {
expect(func(2, 8.8)).toBe(445.7218884076158);
expect(func('2', 8.8)).toBe(445.7218884076158);
expect(func('2', '8.8')).toBe(445.7218884076158);
expect(func('2', '8.8', 6, 0.4)).toBe(445.7218884076158);
expect(() => func('foo', ' ', 'bar', ' baz')).toThrow('VALUE');
expect(() => func('foo', 2)).toThrow('VALUE');
expect(func("2", 8.8)).toBe(445.7218884076158);
expect(func("2", "8.8")).toBe(445.7218884076158);
expect(func("2", "8.8", 6, 0.4)).toBe(445.7218884076158);
expect(() => func("foo", " ", "bar", " baz")).toThrow("VALUE");
expect(() => func("foo", 2)).toThrow("VALUE");
});
});

View File

@ -5,170 +5,180 @@ import {
columnLabelToIndex,
rowIndexToLabel,
rowLabelToIndex,
} from '../../../src/helper/cell';
} from "../../../src/helper/cell";
describe('.extractLabel()', () => {
it('should correctly extract coordinates', () => {
expect(extractLabel('A1')).toMatchObject([
describe(".extractLabel()", () => {
it("should correctly extract coordinates", () => {
expect(extractLabel("A1")).toMatchObject([
{
index: 0,
label: '1',
label: "1",
isAbsolute: false,
},
{
index: 0,
label: 'A',
label: "A",
isAbsolute: false,
},
]);
expect(extractLabel('a1')).toMatchObject([
expect(extractLabel("a1")).toMatchObject([
{
index: 0,
label: '1',
label: "1",
isAbsolute: false,
},
{
index: 0,
label: 'A',
label: "A",
isAbsolute: false,
},
]);
expect(extractLabel('A$1')).toMatchObject([
expect(extractLabel("A$1")).toMatchObject([
{
index: 0,
label: '1',
label: "1",
isAbsolute: true,
},
{
index: 0,
label: 'A',
label: "A",
isAbsolute: false,
},
]);
expect(extractLabel('a$1')).toMatchObject([
expect(extractLabel("a$1")).toMatchObject([
{
index: 0,
label: '1',
label: "1",
isAbsolute: true,
},
{
index: 0,
label: 'A',
label: "A",
isAbsolute: false,
},
]);
expect(extractLabel('$A1')).toMatchObject([
expect(extractLabel("$A1")).toMatchObject([
{
index: 0,
label: '1',
label: "1",
isAbsolute: false,
},
{
index: 0,
label: 'A',
label: "A",
isAbsolute: true,
},
]);
expect(extractLabel('$A$1')).toMatchObject([
expect(extractLabel("$A$1")).toMatchObject([
{
index: 0,
label: '1',
label: "1",
isAbsolute: true,
},
{
index: 0,
label: 'A',
label: "A",
isAbsolute: true,
},
]);
expect(extractLabel('$AG199')).toMatchObject([
expect(extractLabel("$AG199")).toMatchObject([
{
index: 198,
label: '199',
label: "199",
isAbsolute: false,
},
{
index: 32,
label: 'AG',
label: "AG",
isAbsolute: true,
},
]);
expect(extractLabel('$Ag199')).toMatchObject([
expect(extractLabel("$Ag199")).toMatchObject([
{
index: 198,
label: '199',
label: "199",
isAbsolute: false,
},
{
index: 32,
label: 'AG',
label: "AG",
isAbsolute: true,
},
]);
expect(extractLabel('$$AG199')).toMatchObject([]);
expect(extractLabel('AG$$199')).toMatchObject([]);
expect(extractLabel("$$AG199")).toMatchObject([]);
expect(extractLabel("AG$$199")).toMatchObject([]);
expect(extractLabel(null)).toMatchObject([]);
expect(extractLabel(void 0)).toMatchObject([]);
expect(extractLabel(0)).toMatchObject([]);
});
});
describe('.toLabel()', () => {
it('should correctly convert coords to label ', () => {
expect(toLabel({index: 0, isAbsolute: false}, {index: 0, isAbsolute: false})).toBe('A1');
expect(toLabel({index: 0, isAbsolute: true}, {index: 0, isAbsolute: false})).toBe('A$1');
expect(toLabel({index: 0, isAbsolute: true}, {index: 0, isAbsolute: true})).toBe('$A$1');
expect(toLabel({index: 44, isAbsolute: true}, {index: 20, isAbsolute: true})).toBe('$U$45');
expect(toLabel({index: 1, isAbsolute: false}, {index: 20, isAbsolute: true})).toBe('$U2');
describe(".toLabel()", () => {
it("should correctly convert coords to label ", () => {
expect(
toLabel({ index: 0, isAbsolute: false }, { index: 0, isAbsolute: false })
).toBe("A1");
expect(
toLabel({ index: 0, isAbsolute: true }, { index: 0, isAbsolute: false })
).toBe("A$1");
expect(
toLabel({ index: 0, isAbsolute: true }, { index: 0, isAbsolute: true })
).toBe("$A$1");
expect(
toLabel({ index: 44, isAbsolute: true }, { index: 20, isAbsolute: true })
).toBe("$U$45");
expect(
toLabel({ index: 1, isAbsolute: false }, { index: 20, isAbsolute: true })
).toBe("$U2");
});
});
describe('.columnIndexToLabel()', () => {
it('should correctly convert column index to label ', () => {
expect(columnIndexToLabel(-100)).toBe('');
expect(columnIndexToLabel(-1)).toBe('');
expect(columnIndexToLabel(0)).toBe('A');
expect(columnIndexToLabel(1)).toBe('B');
expect(columnIndexToLabel(10)).toBe('K');
expect(columnIndexToLabel(100)).toBe('CW');
expect(columnIndexToLabel(1000)).toBe('ALM');
expect(columnIndexToLabel(10000)).toBe('NTQ');
describe(".columnIndexToLabel()", () => {
it("should correctly convert column index to label ", () => {
expect(columnIndexToLabel(-100)).toBe("");
expect(columnIndexToLabel(-1)).toBe("");
expect(columnIndexToLabel(0)).toBe("A");
expect(columnIndexToLabel(1)).toBe("B");
expect(columnIndexToLabel(10)).toBe("K");
expect(columnIndexToLabel(100)).toBe("CW");
expect(columnIndexToLabel(1000)).toBe("ALM");
expect(columnIndexToLabel(10000)).toBe("NTQ");
});
});
describe('.columnLabelToIndex()', () => {
it('should correctly convert column label to index', () => {
expect(columnLabelToIndex('')).toBe(-1);
expect(columnLabelToIndex('')).toBe(-1);
expect(columnLabelToIndex('A')).toBe(0);
expect(columnLabelToIndex('B')).toBe(1);
expect(columnLabelToIndex('K')).toBe(10);
expect(columnLabelToIndex('k')).toBe(10);
expect(columnLabelToIndex('CW')).toBe(100);
expect(columnLabelToIndex('ALM')).toBe(1000);
expect(columnLabelToIndex('aLM')).toBe(1000);
expect(columnLabelToIndex('NTQ')).toBe(10000);
describe(".columnLabelToIndex()", () => {
it("should correctly convert column label to index", () => {
expect(columnLabelToIndex("")).toBe(-1);
expect(columnLabelToIndex("")).toBe(-1);
expect(columnLabelToIndex("A")).toBe(0);
expect(columnLabelToIndex("B")).toBe(1);
expect(columnLabelToIndex("K")).toBe(10);
expect(columnLabelToIndex("k")).toBe(10);
expect(columnLabelToIndex("CW")).toBe(100);
expect(columnLabelToIndex("ALM")).toBe(1000);
expect(columnLabelToIndex("aLM")).toBe(1000);
expect(columnLabelToIndex("NTQ")).toBe(10000);
});
});
describe('.rowIndexToLabel()', () => {
it('should correctly convert row index to label ', () => {
expect(rowIndexToLabel(-100)).toBe('');
expect(rowIndexToLabel(-1)).toBe('');
expect(rowIndexToLabel(0)).toBe('1');
expect(rowIndexToLabel(1)).toBe('2');
expect(rowIndexToLabel(10)).toBe('11');
expect(rowIndexToLabel(100)).toBe('101');
describe(".rowIndexToLabel()", () => {
it("should correctly convert row index to label ", () => {
expect(rowIndexToLabel(-100)).toBe("");
expect(rowIndexToLabel(-1)).toBe("");
expect(rowIndexToLabel(0)).toBe("1");
expect(rowIndexToLabel(1)).toBe("2");
expect(rowIndexToLabel(10)).toBe("11");
expect(rowIndexToLabel(100)).toBe("101");
});
});
describe('.rowLabelToIndex()', () => {
it('should correctly convert row label to index', () => {
expect(rowLabelToIndex('')).toBe(-1);
expect(rowLabelToIndex('0')).toBe(-1);
expect(rowLabelToIndex('1')).toBe(0);
expect(rowLabelToIndex('2')).toBe(1);
expect(rowLabelToIndex('100')).toBe(99);
expect(rowLabelToIndex('92')).toBe(91);
describe(".rowLabelToIndex()", () => {
it("should correctly convert row label to index", () => {
expect(rowLabelToIndex("")).toBe(-1);
expect(rowLabelToIndex("0")).toBe(-1);
expect(rowLabelToIndex("1")).toBe(0);
expect(rowLabelToIndex("2")).toBe(1);
expect(rowLabelToIndex("100")).toBe(99);
expect(rowLabelToIndex("92")).toBe(91);
});
});

View File

@ -1,31 +1,31 @@
import {toNumber, invertNumber} from '../../../src/helper/number';
import { toNumber, invertNumber } from "../../../src/helper/number";
describe('.toNumber()', () => {
it('should correctly convert passed value into number', () => {
describe(".toNumber()", () => {
it("should correctly convert passed value into number", () => {
expect(toNumber(-100)).toBe(-100);
expect(toNumber(-1)).toBe(-1);
expect(toNumber(19)).toBe(19);
expect(toNumber(19.9)).toBe(19.9);
expect(toNumber(0.9)).toBe(0.9);
expect(toNumber('0.9')).toBe(0.9);
expect(toNumber('0')).toBe(0);
expect(toNumber('-10')).toBe(-10);
expect(toNumber(' -10 ')).toBe(-10);
expect(isNaN(toNumber('foo'))).toBe(true);
expect(toNumber("0.9")).toBe(0.9);
expect(toNumber("0")).toBe(0);
expect(toNumber("-10")).toBe(-10);
expect(toNumber(" -10 ")).toBe(-10);
expect(isNaN(toNumber("foo"))).toBe(true);
});
});
describe('.invertNumber()', () => {
it('should correctly invert number', () => {
describe(".invertNumber()", () => {
it("should correctly invert number", () => {
expect(invertNumber(-100)).toBe(100);
expect(invertNumber(-1)).toBe(1);
expect(invertNumber(19)).toBe(-19);
expect(invertNumber(19.9)).toBe(-19.9);
expect(invertNumber(0.9)).toBe(-0.9);
expect(invertNumber('0.9')).toBe(-0.9);
expect(invertNumber('0')).toBe(-0);
expect(invertNumber('-10')).toBe(10);
expect(invertNumber(' -10 ')).toBe(10);
expect(isNaN(invertNumber('foo'))).toBe(true);
expect(invertNumber("0.9")).toBe(-0.9);
expect(invertNumber("0")).toBe(-0);
expect(invertNumber("-10")).toBe(10);
expect(invertNumber(" -10 ")).toBe(10);
expect(isNaN(invertNumber("foo"))).toBe(true);
});
});

View File

@ -1,9 +1,9 @@
import {trimEdges} from '../../../src/helper/string';
import { trimEdges } from "../../../src/helper/string";
describe('.trimEdges()', () => {
it('should correctly trim edges', () => {
expect(trimEdges('hello')).toBe('ell');
expect(trimEdges('hello', 1)).toBe('ell');
expect(trimEdges('hello', 2)).toBe('l');
describe(".trimEdges()", () => {
it("should correctly trim edges", () => {
expect(trimEdges("hello")).toBe("ell");
expect(trimEdges("hello", 1)).toBe("ell");
expect(trimEdges("hello", 2)).toBe("l");
});
});

View File

@ -1,71 +1,71 @@
import * as lib from '../../src/index';
import * as lib from "../../src/index";
describe('Public API', () => {
it('Parser should be defined', () => {
describe("Public API", () => {
it("Parser should be defined", () => {
expect(lib.Parser).toBeInstanceOf(Function);
});
it('SUPPORTED_FORMULAS should be defined', () => {
it("SUPPORTED_FORMULAS should be defined", () => {
expect(lib.SUPPORTED_FORMULAS).toBeInstanceOf(Array);
});
it('ERROR should be defined', () => {
it("ERROR should be defined", () => {
expect(lib.ERROR).toBeDefined();
});
it('ERROR_DIV_ZERO should be defined', () => {
it("ERROR_DIV_ZERO should be defined", () => {
expect(lib.ERROR_DIV_ZERO).toBeDefined();
});
it('ERROR_NAME should be defined', () => {
it("ERROR_NAME should be defined", () => {
expect(lib.ERROR_NAME).toBeDefined();
});
it('ERROR_NOT_AVAILABLE should be defined', () => {
it("ERROR_NOT_AVAILABLE should be defined", () => {
expect(lib.ERROR_NOT_AVAILABLE).toBeDefined();
});
it('ERROR_NULL should be defined', () => {
it("ERROR_NULL should be defined", () => {
expect(lib.ERROR_NULL).toBeDefined();
});
it('ERROR_NUM should be defined', () => {
it("ERROR_NUM should be defined", () => {
expect(lib.ERROR_NUM).toBeDefined();
});
it('ERROR_REF should be defined', () => {
it("ERROR_REF should be defined", () => {
expect(lib.ERROR_REF).toBeDefined();
});
it('ERROR_VALUE should be defined', () => {
it("ERROR_VALUE should be defined", () => {
expect(lib.ERROR_VALUE).toBeDefined();
});
it('error should be defined', () => {
it("error should be defined", () => {
expect(lib.error).toBeDefined();
});
it('extractLabel should be defined', () => {
it("extractLabel should be defined", () => {
expect(lib.extractLabel).toBeDefined();
});
it('toLabel should be defined', () => {
it("toLabel should be defined", () => {
expect(lib.toLabel).toBeDefined();
});
it('columnIndexToLabel should be defined', () => {
it("columnIndexToLabel should be defined", () => {
expect(lib.columnIndexToLabel).toBeDefined();
});
it('columnLabelToIndex should be defined', () => {
it("columnLabelToIndex should be defined", () => {
expect(lib.columnLabelToIndex).toBeDefined();
});
it('rowIndexToLabel should be defined', () => {
it("rowIndexToLabel should be defined", () => {
expect(lib.rowIndexToLabel).toBeDefined();
});
it('rowLabelToIndex should be defined', () => {
it("rowLabelToIndex should be defined", () => {
expect(lib.rowLabelToIndex).toBeDefined();
});
});

View File

@ -1,6 +1,6 @@
import Parser from '../../src/parser';
import Parser from "../../src/parser";
describe('Parser', () => {
describe("Parser", () => {
let parser;
beforeEach(() => {
@ -10,330 +10,409 @@ describe('Parser', () => {
parser = null;
});
describe('.parse()', () => {
it('should be defined', () => {
describe(".parse()", () => {
it("should be defined", () => {
expect(parser.parse).toBeInstanceOf(Function);
});
it('should not internally call `parse` method of grammar parser object when an empty string was passed', () => {
it("should not internally call `parse` method of grammar parser object when an empty string was passed", () => {
parser.parser.parse = jest.fn();
parser.parse('');
parser.parse("");
expect(parser.parser.parse).not.toHaveBeenCalled();
});
it('should return `#ERROR!` when parser throws unknown exception', () => {
it("should return `#ERROR!` when parser throws unknown exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('some error');
throw Error("some error");
});
expect(parser.parse('foo')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should return `#ERROR!` when parser throws `#ERROR!` exception', () => {
it("should return `#ERROR!` when parser throws `#ERROR!` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#ERROR!');
throw Error("#ERROR!");
});
expect(parser.parse('foo')).toMatchObject({error: '#ERROR!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#ERROR!",
result: null,
});
});
it('should return `#DIV/0!` when parser throws `#DIV/0!` exception', () => {
it("should return `#DIV/0!` when parser throws `#DIV/0!` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#DIV/0!');
throw Error("#DIV/0!");
});
expect(parser.parse('foo')).toMatchObject({error: '#DIV/0!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#DIV/0!",
result: null,
});
});
it('should return `#NAME?` when parser throws `#NAME?` exception', () => {
it("should return `#NAME?` when parser throws `#NAME?` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#NAME?');
throw Error("#NAME?");
});
expect(parser.parse('foo')).toMatchObject({error: '#NAME?', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#NAME?",
result: null,
});
});
it('should return `#N/A` when parser throws `#N/A` exception', () => {
it("should return `#N/A` when parser throws `#N/A` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#N/A');
throw Error("#N/A");
});
expect(parser.parse('foo')).toMatchObject({error: '#N/A', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#N/A",
result: null,
});
});
it('should return `#NULL!` when parser throws `#NULL!` exception', () => {
it("should return `#NULL!` when parser throws `#NULL!` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#NULL!');
throw Error("#NULL!");
});
expect(parser.parse('foo')).toMatchObject({error: '#NULL!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#NULL!",
result: null,
});
});
it('should return `#NUM!` when parser throws `#NUM!` exception', () => {
it("should return `#NUM!` when parser throws `#NUM!` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#NUM!');
throw Error("#NUM!");
});
expect(parser.parse('foo')).toMatchObject({error: '#NUM!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#NUM!",
result: null,
});
});
it('should return `#REF!` when parser throws `#REF!` exception', () => {
it("should return `#REF!` when parser throws `#REF!` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#REF!');
throw Error("#REF!");
});
expect(parser.parse('foo')).toMatchObject({error: '#REF!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#REF!",
result: null,
});
});
it('should return `#VALUE!` when parser throws `#VALUE!` exception', () => {
it("should return `#VALUE!` when parser throws `#VALUE!` exception", () => {
parser.parser.parse = jest.fn(() => {
throw Error('#VALUE!');
throw Error("#VALUE!");
});
expect(parser.parse('foo')).toMatchObject({error: '#VALUE!', result: null});
expect(parser.parse("foo")).toMatchObject({
error: "#VALUE!",
result: null,
});
});
it('should not return `#ERROR!` when parser evaluate expression as `ERROR`', () => {
parser.parser.parse = jest.fn(() => 'ERROR');
it("should not return `#ERROR!` when parser evaluate expression as `ERROR`", () => {
parser.parser.parse = jest.fn(() => "ERROR");
expect(parser.parse('foo')).toMatchObject({error: null, result: 'ERROR'});
expect(parser.parse("foo")).toMatchObject({
error: null,
result: "ERROR",
});
});
it('should not return `#ERROR!` when parser evaluate expression as `#ERROR!`', () => {
parser.parser.parse = jest.fn(() => '#ERROR!');
it("should not return `#ERROR!` when parser evaluate expression as `#ERROR!`", () => {
parser.parser.parse = jest.fn(() => "#ERROR!");
expect(parser.parse('foo')).toMatchObject({error: null, result: '#ERROR!'});
expect(parser.parse("foo")).toMatchObject({
error: null,
result: "#ERROR!",
});
});
});
describe('.setVariable()/.getVariable()', () => {
it('should return default variables', () => {
expect(parser.getVariable('TRUE')).toBe(true);
expect(parser.getVariable('FALSE')).toBe(false);
expect(parser.getVariable('NULL')).toBe(null);
expect(parser.getVariable('foo')).not.toBeDefined();
describe(".setVariable()/.getVariable()", () => {
it("should return default variables", () => {
expect(parser.getVariable("TRUE")).toBe(true);
expect(parser.getVariable("FALSE")).toBe(false);
expect(parser.getVariable("NULL")).toBe(null);
expect(parser.getVariable("foo")).not.toBeDefined();
});
it('should return custom variables', () => {
parser.setVariable('foo', 1234);
parser.setVariable('bar', '1234');
parser.setVariable('baz', [1, 2]);
it("should return custom variables", () => {
parser.setVariable("foo", 1234);
parser.setVariable("bar", "1234");
parser.setVariable("baz", [1, 2]);
expect(parser.getVariable('foo')).toBe(1234);
expect(parser.getVariable('bar')).toBe('1234');
expect(parser.getVariable('baz')).toMatchObject([1, 2]);
expect(parser.getVariable("foo")).toBe(1234);
expect(parser.getVariable("bar")).toBe("1234");
expect(parser.getVariable("baz")).toMatchObject([1, 2]);
});
});
describe('.setFunction()/.getFunction()', () => {
it('should return custom functions', () => {
parser.setFunction('foo', () => 1234);
parser.setFunction('bar', (params) => params[0] + params[1]);
describe(".setFunction()/.getFunction()", () => {
it("should return custom functions", () => {
parser.setFunction("foo", () => 1234);
parser.setFunction("bar", (params) => params[0] + params[1]);
expect(parser.getFunction('foo')()).toBe(1234);
expect(parser.getFunction('bar')([1, 2])).toBe(3);
expect(parser.getFunction("foo")()).toBe(1234);
expect(parser.getFunction("bar")([1, 2])).toBe(3);
});
});
describe('._callVariable()', () => {
it('should return error (NAME) when variable not set', () => {
describe("._callVariable()", () => {
it("should return error (NAME) when variable not set", () => {
parser.getVariable = jest.fn(() => void 0);
expect(parser._callVariable.bind(parser)).toThrow(/NAME/);
});
it('should return variable when it was set', () => {
parser.getVariable = jest.fn((name) => (name === 'bar' ? 'foo' : 'baz'));
it("should return variable when it was set", () => {
parser.getVariable = jest.fn((name) => (name === "bar" ? "foo" : "baz"));
expect(parser._callVariable('bar')).toBe('foo');
expect(parser._callVariable('barrr')).toBe('baz');
expect(parser._callVariable("bar")).toBe("foo");
expect(parser._callVariable("barrr")).toBe("baz");
});
it('should return variable set by event emitter', () => {
parser.getVariable = jest.fn(() => 'baz');
it("should return variable set by event emitter", () => {
parser.getVariable = jest.fn(() => "baz");
parser.on('callVariable', (name, done) => {
done(name === 'bar' ? 'foo' : void 0);
parser.on("callVariable", (name, done) => {
done(name === "bar" ? "foo" : void 0);
});
expect(parser._callVariable('bar')).toBe('foo');
expect(parser._callVariable('barrr')).toBe('baz');
expect(parser._callVariable("bar")).toBe("foo");
expect(parser._callVariable("barrr")).toBe("baz");
});
});
describe('._callFunction()', () => {
it('should return error (NAME) when function not set', () => {
expect(() => parser._callFunction('NOT_DEFINED()')).toThrow(/NAME/);
describe("._callFunction()", () => {
it("should return error (NAME) when function not set", () => {
expect(() => parser._callFunction("NOT_DEFINED()")).toThrow(/NAME/);
});
it('should call predefined function', () => {
it("should call predefined function", () => {
parser.getFunction = jest.fn(() => void 0);
expect(parser._callFunction('SUM', [1, 2])).toBe(3);
expect(parser._callFunction("SUM", [1, 2])).toBe(3);
});
it('should call custom funciton when it was set', () => {
it("should call custom funciton when it was set", () => {
parser.getFunction = jest.fn(() => (params) => params[0] + 1);
expect(parser._callFunction('ADD_1', [2])).toBe(3);
expect(parser._callFunction("ADD_1", [2])).toBe(3);
});
it('should return variable set by event emitter', () => {
it("should return variable set by event emitter", () => {
parser.getFunction = jest.fn(() => (params) => params[0] + 1);
parser.on('callFunction', (name, params, done) => {
done(name === 'OVERRIDDEN' ? params[0] + 2 : void 0);
parser.on("callFunction", (name, params, done) => {
done(name === "OVERRIDDEN" ? params[0] + 2 : void 0);
});
expect(parser._callFunction('ADD_1', [2])).toBe(3);
expect(parser._callFunction('OVERRIDDEN', [2])).toBe(4);
expect(parser._callFunction("ADD_1", [2])).toBe(3);
expect(parser._callFunction("OVERRIDDEN", [2])).toBe(4);
});
});
describe('._callCellValue()', () => {
it('should return undefined if under specified coordinates data value not exist', () => {
expect(parser._callCellValue('A1')).not.toBeDefined();
describe("._callCellValue()", () => {
it("should return undefined if under specified coordinates data value not exist", () => {
expect(parser._callCellValue("A1")).not.toBeDefined();
});
it('should return value under specified coordinates', () => {
parser.on('callCellValue', (cell, done) => {
const {row, column} = cell;
it("should return value under specified coordinates", () => {
parser.on("callCellValue", (cell, done) => {
const { row, column } = cell;
let value;
if (row.index === 0 && column.index === 2) {
value = '4';
value = "4";
} else if (row.index === 0 && column.index === 7) {
value = 45;
} else if (row.index === 2 && column.index === 7) {
value = [1, 2, 3];
} else if (row.index === 3 && column.index === 7 && column.isAbsolute) {
value = true;
} else if (row.index === 4 && row.isAbsolute && column.index === 7 && column.isAbsolute) {
} else if (
row.index === 4 &&
row.isAbsolute &&
column.index === 7 &&
column.isAbsolute
) {
value = 0.9;
}
done(value);
});
expect(parser._callCellValue('A1')).toBe(void 0);
expect(parser._callCellValue('C1')).toBe('4');
expect(parser._callCellValue('H1')).toBe(45);
expect(parser._callCellValue('H3')).toMatchObject([1, 2, 3]);
expect(parser._callCellValue('$H4')).toBe(true);
expect(parser._callCellValue('$H$5')).toBe(0.9);
expect(parser._callCellValue("A1")).toBe(void 0);
expect(parser._callCellValue("C1")).toBe("4");
expect(parser._callCellValue("H1")).toBe(45);
expect(parser._callCellValue("H3")).toMatchObject([1, 2, 3]);
expect(parser._callCellValue("$H4")).toBe(true);
expect(parser._callCellValue("$H$5")).toBe(0.9);
});
});
describe('._callRangeValue()', () => {
it('should return an empty array if under specified coordinates data value not exist', () => {
expect(parser._callRangeValue('A1', 'B2')).toMatchObject([]);
describe("._callRangeValue()", () => {
it("should return an empty array if under specified coordinates data value not exist", () => {
expect(parser._callRangeValue("A1", "B2")).toMatchObject([]);
});
it('should return value under specified coordinates', () => {
parser.on('callRangeValue', (firstCell, lastCell, done) => {
const {row: row1, column: column1} = firstCell;
const {row: row2, column: column2} = lastCell;
it("should return value under specified coordinates", () => {
parser.on("callRangeValue", (firstCell, lastCell, done) => {
const { row: row1, column: column1 } = firstCell;
const { row: row2, column: column2 } = lastCell;
let value;
if (row1.index === 0 && column1.index === 2 && row2.index === 3 && column2.index === 3) {
value = [[1, 2], [4, 5]];
} else if (row1.index === 0 && row1.isAbsolute && column1.index === 0 &&
row2.index === 3 && column2.index === 3 && column2.isAbsolute) {
value = [['a', 'b'], ['z', 'd']];
} else if (row1.index === 0 && row1.isAbsolute && column1.index === 0 && column1.isAbsolute &&
row2.index === 4 && row2.isAbsolute && column2.index === 4 && column2.isAbsolute) {
value = [[true, false], [true, true]];
} else if (row1.index === 4 && row1.isAbsolute && column1.index === 7 && column1.isAbsolute) {
if (
row1.index === 0 &&
column1.index === 2 &&
row2.index === 3 &&
column2.index === 3
) {
value = [
[1, 2],
[4, 5],
];
} else if (
row1.index === 0 &&
row1.isAbsolute &&
column1.index === 0 &&
row2.index === 3 &&
column2.index === 3 &&
column2.isAbsolute
) {
value = [
["a", "b"],
["z", "d"],
];
} else if (
row1.index === 0 &&
row1.isAbsolute &&
column1.index === 0 &&
column1.isAbsolute &&
row2.index === 4 &&
row2.isAbsolute &&
column2.index === 4 &&
column2.isAbsolute
) {
value = [
[true, false],
[true, true],
];
} else if (
row1.index === 4 &&
row1.isAbsolute &&
column1.index === 7 &&
column1.isAbsolute
) {
value = 0.9;
}
done(value);
});
expect(parser._callRangeValue('C1', 'D4')).toMatchObject([[1, 2], [4, 5]]);
expect(parser._callRangeValue('A$1', '$D4')).toMatchObject([['a', 'b'], ['z', 'd']]);
expect(parser._callRangeValue('$A$1', '$E$5')).toMatchObject([[true, false], [true, true]]);
expect(parser._callRangeValue("C1", "D4")).toMatchObject([
[1, 2],
[4, 5],
]);
expect(parser._callRangeValue("A$1", "$D4")).toMatchObject([
["a", "b"],
["z", "d"],
]);
expect(parser._callRangeValue("$A$1", "$E$5")).toMatchObject([
[true, false],
[true, true],
]);
});
it('should convert coordinates in top-left bottom-right format (from bottom-left to top-right)', () => {
it("should convert coordinates in top-left bottom-right format (from bottom-left to top-right)", () => {
const cb = jest.fn();
parser.on('callRangeValue', cb);
parser._callRangeValue('$A$9', 'B2');
parser.on("callRangeValue", cb);
parser._callRangeValue("$A$9", "B2");
const startCell = {
row: {index: 1, isAbsolute: false, label: '2'},
column: {index: 0, isAbsolute: true, label: 'A'},
label: '$A2',
row: { index: 1, isAbsolute: false, label: "2" },
column: { index: 0, isAbsolute: true, label: "A" },
label: "$A2",
};
const endCell = {
row: {index: 8, isAbsolute: true, label: '9'},
column: {index: 1, isAbsolute: false, label: 'B'},
label: 'B$9',
row: { index: 8, isAbsolute: true, label: "9" },
column: { index: 1, isAbsolute: false, label: "B" },
label: "B$9",
};
expect(cb).toHaveBeenCalledWith(startCell, endCell, expect.anything());
});
it('should convert coordinates in top-left bottom-right format (from top-right to bottom-left)', () => {
it("should convert coordinates in top-left bottom-right format (from top-right to bottom-left)", () => {
const cb = jest.fn();
parser.on('callRangeValue', cb);
parser._callRangeValue('B$2', 'A$8');
parser.on("callRangeValue", cb);
parser._callRangeValue("B$2", "A$8");
const startCell = {
row: {index: 1, isAbsolute: true, label: '2'},
column: {index: 0, isAbsolute: false, label: 'A'},
label: 'A$2',
row: { index: 1, isAbsolute: true, label: "2" },
column: { index: 0, isAbsolute: false, label: "A" },
label: "A$2",
};
const endCell = {
row: {index: 7, isAbsolute: true, label: '8'},
column: {index: 1, isAbsolute: false, label: 'B'},
label: 'B$8',
row: { index: 7, isAbsolute: true, label: "8" },
column: { index: 1, isAbsolute: false, label: "B" },
label: "B$8",
};
expect(cb).toHaveBeenCalledWith(startCell, endCell, expect.anything());
});
});
describe('._throwError()', () => {
it('should throw general error', () => {
expect(() => parser._throwError('#ERROR!')).toThrow('ERROR');
describe("._throwError()", () => {
it("should throw general error", () => {
expect(() => parser._throwError("#ERROR!")).toThrow("ERROR");
});
it('should throw dividing by 0 error', () => {
expect(() => parser._throwError('#DIV/0!')).toThrow('DIV/0');
it("should throw dividing by 0 error", () => {
expect(() => parser._throwError("#DIV/0!")).toThrow("DIV/0");
});
it('should throw name error', () => {
expect(() => parser._throwError('#NAME?')).toThrow('NAME');
it("should throw name error", () => {
expect(() => parser._throwError("#NAME?")).toThrow("NAME");
});
it('should throw not available error', () => {
expect(() => parser._throwError('#N/A')).toThrow('N/A');
it("should throw not available error", () => {
expect(() => parser._throwError("#N/A")).toThrow("N/A");
});
it('should throw null error', () => {
expect(() => parser._throwError('#NULL!')).toThrow('NULL');
it("should throw null error", () => {
expect(() => parser._throwError("#NULL!")).toThrow("NULL");
});
it('should throw num error', () => {
expect(() => parser._throwError('#NUM!')).toThrow('NUM');
it("should throw num error", () => {
expect(() => parser._throwError("#NUM!")).toThrow("NUM");
});
it('should throw ref error', () => {
expect(() => parser._throwError('#REF!')).toThrow('REF');
it("should throw ref error", () => {
expect(() => parser._throwError("#REF!")).toThrow("REF");
});
it('should throw value error', () => {
expect(() => parser._throwError('#VALUE!')).toThrow('VALUE');
it("should throw value error", () => {
expect(() => parser._throwError("#VALUE!")).toThrow("VALUE");
});
it('should return general error if value not matches to any of known errors', () => {
expect(() => parser._throwError('VALUE foo')).toThrow('ERROR');
it("should return general error if value not matches to any of known errors", () => {
expect(() => parser._throwError("VALUE foo")).toThrow("ERROR");
});
});
});

View File

@ -1,7 +1,7 @@
import SUPPORTED_FORMULAS from '../../src/supported-formulas';
import SUPPORTED_FORMULAS from "../../src/supported-formulas";
describe('.SUPPORTED_FORMULAS', () => {
it('should be defined', () => {
describe(".SUPPORTED_FORMULAS", () => {
it("should be defined", () => {
expect(SUPPORTED_FORMULAS.length).toBe(385);
});
});

View File

@ -1,42 +1,42 @@
'use strict';
"use strict";
const webpack = require('webpack');
const path = require('path');
const webpack = require("webpack");
const path = require("path");
const ROOT_DIRECTORY = process.cwd();
const NODE_ENV = process.env.NODE_ENV;
const config = {
mode: 'production',
mode: "production",
devtool: false,
entry: {
main: path.resolve(ROOT_DIRECTORY, 'src/index.js'),
main: path.resolve(ROOT_DIRECTORY, "src/index.js"),
},
output: {
library: 'formulaParser',
libraryTarget: 'umd',
path: path.resolve(ROOT_DIRECTORY, 'dist'),
filename: `formula-parser${NODE_ENV === 'production' ? '.min' : ''}.js`,
library: "formulaParser",
libraryTarget: "umd",
path: path.resolve(ROOT_DIRECTORY, "dist"),
filename: `formula-parser${NODE_ENV === "production" ? ".min" : ""}.js`,
umdNamedDefine: true,
},
module: {
rules: [
{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules|grammar\-parser\.js$/
loaders: ["babel-loader"],
exclude: /node_modules|grammar\-parser\.js$/,
},
]
],
},
optimization: {
minimize: NODE_ENV === 'production',
minimize: NODE_ENV === "production",
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(NODE_ENV)
})
]
"process.env.NODE_ENV": JSON.stringify(NODE_ENV),
}),
],
};
module.exports = config;

View File

@ -7,7 +7,7 @@
left: 197px;
border-radius: 6px;
box-shadow: 0 2px 4px rgb(0 0 0 / 20%);
border: 1px solid rgba(0, 0, 0, .2);
border: 1px solid rgba(0, 0, 0, 0.2);
}
#fortune-change-color .color-reset {
@ -63,4 +63,4 @@
border: 1px solid #0188fb;
color: #fff;
margin-right: -4px;
}
}

View File

@ -34,7 +34,11 @@ export const ChangeColor: React.FC<Props> = ({ triggerParentUpdate }) => {
return (
<div id="fortune-change-color">
<div className="color-reset" onClick={() => setSelectColor(undefined)}>
<div
className="color-reset"
onClick={() => setSelectColor(undefined)}
tabIndex={0}
>
{sheetconfig.resetColor}
</div>
<div className="custom-color">
@ -55,6 +59,7 @@ export const ChangeColor: React.FC<Props> = ({ triggerParentUpdate }) => {
onClick={() => {
certainBtn();
}}
tabIndex={0}
>
{button.confirm}
</div>

View File

@ -325,6 +325,7 @@ const ConditionRules: React.FC<{ type: string }> = ({ type }) => {
// hideDialog();
close("confirm");
}}
tabIndex={0}
>
{button.confirm}
</div>
@ -334,6 +335,7 @@ const ConditionRules: React.FC<{ type: string }> = ({ type }) => {
// hideDialog();
close("close");
}}
tabIndex={0}
>
{button.cancel}
</div>

View File

@ -3,7 +3,7 @@
top: -8px;
box-shadow: 0 2px 4px rgb(0 0 0 / 20%);
background: #fff;
border: 1px solid rgba(0, 0, 0, .2);
border: 1px solid rgba(0, 0, 0, 0.2);
cursor: default;
font-size: 12px;
z-index: 1004;
@ -34,8 +34,6 @@
margin-bottom: 6px;
}
.condition-rules .button-basic {
display: inline-block;
margin-bottom: 0;
@ -136,8 +134,8 @@
.condition-rules-select-color {
padding: 2px;
border: solid 1px #E5E5E5;
background: #F5F5F5;
border: solid 1px #e5e5e5;
background: #f5f5f5;
position: absolute;
top: 50%;
left: 50%;
@ -182,4 +180,4 @@
.condition-rules-project-input {
margin: 0px 6px;
}
}

View File

@ -117,6 +117,7 @@ const ConditionalFormat: React.FC<{
setOpen(false);
showDialog(<ConditionRules type={v.text} />);
}}
tabIndex={0}
>
{(conditionformat as any)[v.text]}
<span>{v.value}</span>
@ -165,6 +166,7 @@ const ConditionalFormat: React.FC<{
setOpen(false);
showDialog(<ConditionRules type={v.text} />);
}}
tabIndex={0}
>
{(conditionformat as any)[v.text]}
<span>{v.value}</span>
@ -232,6 +234,7 @@ const ConditionalFormat: React.FC<{
updateItem(ctx, "delSheet");
});
}}
tabIndex={0}
>
{(conditionformat as any)[v]}
</div>

View File

@ -80,6 +80,7 @@ const DateSelectTreeItem: React.FC<{
onExpand?.(item.key, !expand);
setExpand(!expand);
}}
tabIndex={0}
>
{_.isEmpty(item.children) ? (
<div style={{ width: 10 }} />
@ -97,6 +98,7 @@ const DateSelectTreeItem: React.FC<{
onChange(item, !checked);
}}
onClick={(e) => e.stopPropagation()}
tabIndex={0}
/>
<div>{item.text}</div>
<span className="count">{`( ${item.rows.length} )`}</span>
@ -305,6 +307,7 @@ const FilterMenu: React.FC = () => {
key={v.color}
className="item"
onClick={() => onSelectChange(key, v.color, !v.checked)}
tabIndex={0}
>
<div
className="color-label"
@ -540,17 +543,26 @@ const FilterMenu: React.FC = () => {
<div className="luckysheet-filter-byvalue">
<div className="fortune-menuitem-row byvalue-btn-row">
<div>
<span className="fortune-byvalue-btn" onClick={selectAll}>
<span
className="fortune-byvalue-btn"
onClick={selectAll}
tabIndex={0}
>
{filter.filterValueByAllBtn}
</span>
{" - "}
<span className="fortune-byvalue-btn" onClick={clearAll}>
<span
className="fortune-byvalue-btn"
onClick={clearAll}
tabIndex={0}
>
{filter.filterValueByClearBtn}
</span>
{" - "}
<span
className="fortune-byvalue-btn"
onClick={inverseSelect}
tabIndex={0}
>
{filter.filterValueByInverseBtn}
</span>
@ -678,6 +690,7 @@ const FilterMenu: React.FC = () => {
draftCtx.filterContextMenu = undefined;
});
}}
tabIndex={0}
>
{filter.filterConform}
</div>
@ -688,6 +701,7 @@ const FilterMenu: React.FC = () => {
draftCtx.filterContextMenu = undefined;
});
}}
tabIndex={0}
>
{filter.filterCancel}
</div>
@ -698,6 +712,7 @@ const FilterMenu: React.FC = () => {
clearFilter(draftCtx);
});
}}
tabIndex={0}
>
{filter.clearFilter}
</div>
@ -770,6 +785,7 @@ const FilterMenu: React.FC = () => {
draftCtx.filterContextMenu = undefined;
});
}}
tabIndex={0}
>
{filter.filterConform}
</div>

View File

@ -29,6 +29,7 @@ const Menu: React.FC<Props> = ({
onClick={(e) => onClick?.(e, containerRef.current!)}
onMouseLeave={(e) => onMouseLeave?.(e, containerRef.current!)}
onMouseEnter={(e) => onMouseEnter?.(e, containerRef.current!)}
tabIndex={0}
>
<div className="luckysheet-cols-menuitem-content luckysheet-mousedown-cancel">
{children}

View File

@ -49,10 +49,12 @@
/* 右击菜单项目 hover背景色 */
.luckysheet-cols-menu .luckysheet-cols-menuitem:hover,
.luckysheet-cols-menu .luckysheet-cols-menuitem-hover {
background: #EFEFEF;
background: #efefef;
}
.luckysheet-cols-menu .luckysheet-cols-menuitem .luckysheet-cols-menuitem-content {
.luckysheet-cols-menu
.luckysheet-cols-menuitem
.luckysheet-cols-menuitem-content {
position: relative;
color: #333;
cursor: pointer;
@ -67,7 +69,9 @@
padding: 0px;
}
.fortune-filter-menu .luckysheet-cols-menuitem .luckysheet-cols-menuitem-content {
.fortune-filter-menu
.luckysheet-cols-menuitem
.luckysheet-cols-menuitem-content {
padding: 7px 24px;
}
@ -84,7 +88,6 @@
text-decoration: underline;
}
.luckysheet-filter-bycolor-submenu .button-basic,
.fortune-filter-menu .button-basic {
display: flex;
@ -117,7 +120,7 @@
.luckysheet-filter-bycolor-submenu .button-primary,
.fortune-filter-menu .button-primary {
color: white;
background-color: #0188FB;
background-color: #0188fb;
}
.luckysheet-filter-bycolor-submenu .button-primary:hover,
@ -163,7 +166,7 @@
}
.filtermenu-input-container input.luckysheet-mousedown-cancel {
border: 1px solid #A1A1A1;
border: 1px solid #a1a1a1;
}
.filtermenu-input-container input.luckysheet-mousedown-cancel:focus {
@ -226,7 +229,7 @@
font-size: 12px;
padding: 5px 0;
z-index: 1004;
border: 1px solid rgba(0, 0, 0, .2);
border: 1px solid rgba(0, 0, 0, 0.2);
background-color: #ffffff;
}
@ -276,4 +279,4 @@
position: absolute;
top: 3px;
right: -18px;
}
}

View File

@ -135,6 +135,7 @@ const ContextMenu: React.FC = () => {
<input
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
tabIndex={0}
type="text"
className="luckysheet-mousedown-cancel"
placeholder={rightclick.number}
@ -204,6 +205,7 @@ const ContextMenu: React.FC = () => {
<input
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
tabIndex={0}
type="text"
className="luckysheet-mousedown-cancel"
placeholder={rightclick.number}
@ -424,6 +426,7 @@ const ContextMenu: React.FC = () => {
<input
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
tabIndex={0}
type="number"
min={1}
max={545}
@ -484,6 +487,7 @@ const ContextMenu: React.FC = () => {
<input
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
tabIndex={0}
type="number"
min={1}
max={545}

View File

@ -162,6 +162,7 @@ const CustomSort: React.FC<{}> = () => {
});
hideDialog();
}}
tabIndex={0}
>
{sort.confirm}
</div>

View File

@ -103,6 +103,7 @@ const DropDownList: React.FC = () => {
onKeyDown={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
onMouseUp={(e) => e.stopPropagation()}
tabIndex={0}
>
{list.map((v, i) => (
<div
@ -121,6 +122,7 @@ const DropDownList: React.FC = () => {
setDropcownValue(ctx, v, arr);
});
}}
tabIndex={0}
>
<SVGIcon
name="check"

View File

@ -72,6 +72,7 @@ const RangeDialog: React.FC = () => {
onKeyDown={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
onMouseUp={(e) => e.stopPropagation()}
tabIndex={0}
>
<div className="dialog-title">{dataVerification.selectCellRange}</div>
<input
@ -88,6 +89,7 @@ const RangeDialog: React.FC = () => {
});
close();
}}
tabIndex={0}
>
{button.confirm}
</div>
@ -96,6 +98,7 @@ const RangeDialog: React.FC = () => {
onClick={() => {
close();
}}
tabIndex={0}
>
{button.close}
</div>

View File

@ -14,7 +14,7 @@
#fortune-data-verification .box .box-item {
padding: 10px;
border-bottom: 1px solid #E1E4E8;
border-bottom: 1px solid #e1e4e8;
}
#fortune-data-verification .box .box-item .box-item-title {
@ -38,7 +38,6 @@
height: 30px;
line-height: 30px;
margin-bottom: 10px;
}
#fortune-data-verification .box .box-item .show-box-item .check-box input {
@ -124,12 +123,11 @@
margin-right: 10px;
}
#range-dialog {
box-shadow: 0 4px 16px rgb(0 0 0 / 20%);
background: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, .333);
border: 1px solid rgba(0, 0, 0, 0.333);
outline: 0;
position: absolute;
color: #000;
@ -190,5 +188,5 @@
}
#luckysheet-dataVerification-dropdown-List .dropdown-List-item:hover {
background-color: #E1E1E1;
}
background-color: #e1e1e1;
}

View File

@ -250,6 +250,7 @@ const DataVerification: React.FC = () => {
context.dataVerification!.dataRegulation!.value1
);
}}
tabIndex={0}
>
<SVGIcon name="tab" width={18} />
</i>
@ -328,6 +329,7 @@ const DataVerification: React.FC = () => {
context.dataVerification!.dataRegulation!.value1
)
}
tabIndex={0}
>
<SVGIcon name="tab" width={18} />
</i>
@ -643,6 +645,7 @@ const DataVerification: React.FC = () => {
// hideDialog();
btn("confirm");
}}
tabIndex={0}
>
{button.confirm}
</div>
@ -651,6 +654,7 @@ const DataVerification: React.FC = () => {
onClick={() => {
btn("delete");
}}
tabIndex={0}
>
{dataVerification.deleteVerification}
</div>
@ -659,6 +663,7 @@ const DataVerification: React.FC = () => {
onClick={() => {
btn("close");
}}
tabIndex={0}
>
{button.cancel}
</div>

View File

@ -45,7 +45,7 @@
.fortune-message-box-button.button-primary {
color: white;
background-color: #0188FB;
background-color: #0188fb;
}
.fortune-modal-dialog-header {
@ -61,4 +61,4 @@
.fortune-modal-dialog-icon-close:hover {
opacity: 0.7;
}
}

View File

@ -26,7 +26,11 @@ const Dialog: React.FC<Props> = ({
return (
<div className="fortune-dialog" style={containerStyle}>
<div className="fortune-modal-dialog-header">
<div className="fortune-modal-dialog-icon-close" onClick={onCancel}>
<div
className="fortune-modal-dialog-icon-close"
onClick={onCancel}
tabIndex={0}
>
<SVGIcon name="close" style={{ padding: 7, cursor: "pointer" }} />
</div>
</div>
@ -39,6 +43,7 @@ const Dialog: React.FC<Props> = ({
<div
className="fortune-message-box-button button-default"
onClick={onOk}
tabIndex={0}
>
{button.confirm}
</div>
@ -47,12 +52,14 @@ const Dialog: React.FC<Props> = ({
<div
className="fortune-message-box-button button-primary"
onClick={onOk}
tabIndex={0}
>
{button.confirm}
</div>
<div
className="fortune-message-box-button button-default"
onClick={onCancel}
tabIndex={0}
>
{button.cancel}
</div>

View File

@ -169,6 +169,7 @@ const FilterOptions: React.FC<{ getContainer: () => HTMLDivElement }> = ({
showFilterContextMenu(v_adjusted, i);
}}
onDoubleClick={(e) => e.stopPropagation()}
tabIndex={0}
key={i}
style={_.assign(rowOverflowFreezeStyle, columnOverflowFreezeStyle, {
left,

View File

@ -11,12 +11,9 @@
width: 70px;
}
.format-list {
width: 300px;
height: 170px;
border: 1px solid #d4d4d4;
overflow-y: scroll;
}

View File

@ -121,6 +121,7 @@ export const FormatSearch: React.FC<{
onClick={() => {
setSelectedFormatIndex(index);
}}
tabIndex={0}
>
<div>{v.name}</div>
<div>{v.value}</div>
@ -135,12 +136,14 @@ export const FormatSearch: React.FC<{
<div
className="fortune-message-box-button button-primary"
onClick={onConfirm}
tabIndex={0}
>
{button.confirm}
</div>
<div
className="fortune-message-box-button button-default"
onClick={onCancel}
tabIndex={0}
>
{button.cancel}
</div>

View File

@ -60,6 +60,6 @@
}
.listBox.on {
background-color: #8C89FE;
background-color: #8c89fe;
color: #fff;
}

View File

@ -165,6 +165,7 @@ export const FormulaSearch: React.FC<{ onCancel: () => void }> = ({
className={`listBox${index === selectedFuncIndex ? " on" : ""}`}
key={v.n}
onClick={() => setSelectedFuncIndex(index)}
tabIndex={0}
>
<div>{v.n}</div>
<div>{v.a}</div>
@ -176,12 +177,14 @@ export const FormulaSearch: React.FC<{ onCancel: () => void }> = ({
<div
className="fortune-message-box-button button-primary"
onClick={onConfirm}
tabIndex={0}
>
{button.confirm}
</div>
<div
className="fortune-message-box-button button-default"
onClick={onCancel}
tabIndex={0}
>
{button.cancel}
</div>

View File

@ -64,9 +64,9 @@
background-color: white;
padding-top: 7px;
box-sizing: border-box;
color:black;
color: black;
text-align: left;
}
.fortune-fx-input[contenteditable="true"] {
-webkit-user-modify: read-write-plaintext-only;
}
}

View File

@ -118,6 +118,7 @@ const ImgBoxs: React.FC = () => {
});
e.stopPropagation();
}}
tabIndex={0}
>
<div
className="luckysheet-modal-dialog-content"

View File

@ -16,7 +16,6 @@
align-items: center;
}
.fortune-link-modify-modal .link-content {
margin-right: 6px;
}
@ -29,7 +28,7 @@
.fortune-link-modify-modal .divider {
width: 1px;
height: 16px;
margin: 0px 6px ;
margin: 0px 6px;
background-color: #e0e0e0;
flex-shrink: 0;
}
@ -88,7 +87,7 @@
.fortune-link-modify-input.error-input,
.fortune-link-modify-modal .range-selection-input.error-input {
border: 1px solid #EF4E2F !important;
border: 1px solid #ef4e2f !important;
}
.fortune-link-modify-cell-selector {
@ -107,7 +106,7 @@
.fortune-link-modify-modal .modal-title {
font-weight: 500;
font-size: 16px;
color: rgba(0, 0, 0, .88);
color: rgba(0, 0, 0, 0.88);
margin-bottom: 12px;
line-height: 24px;
}
@ -139,8 +138,8 @@
.fortune-link-modify-modal .validation-input-tip {
height: 17px;
font-size: 12px;
color: #EF4E2F;
margin: 3px 0px ;
color: #ef4e2f;
margin: 3px 0px;
}
.fortune-link-modify-modal .button-group {
@ -178,6 +177,6 @@
.fortune-link-modify-modal .button-primary {
color: white;
background-color: #0188FB;
background-color: #0188fb;
margin-left: 14px;
}
}

View File

@ -87,10 +87,18 @@ export const LinkEditCard: React.FC<LinkCardProps> = ({
const renderBottomButton = useCallback(
(onOk: () => void, onCancel: () => void) => (
<div className="button-group">
<div className="button-basic button-default" onClick={onCancel}>
<div
className="button-basic button-default"
onClick={onCancel}
tabIndex={0}
>
{button.cancel}
</div>
<div className="button-basic button-primary" onClick={onOk}>
<div
className="button-basic button-primary"
onClick={onOk}
tabIndex={0}
>
{button.confirm}
</div>
</div>
@ -100,7 +108,7 @@ export const LinkEditCard: React.FC<LinkCardProps> = ({
const renderToolbarButton = useCallback(
(iconId: string, onClick: () => void) => (
<div className="fortune-toolbar-button" onClick={onClick}>
<div className="fortune-toolbar-button" onClick={onClick} tabIndex={0}>
<SVGIcon name={iconId} style={{ width: 18, height: 18 }} />
</div>
),
@ -164,6 +172,7 @@ export const LinkEditCard: React.FC<LinkCardProps> = ({
)
);
}}
tabIndex={0}
>
{linkType === "webpage"
? insertLink.openLink
@ -210,6 +219,7 @@ export const LinkEditCard: React.FC<LinkCardProps> = ({
<div
className="modal-icon-close"
onClick={() => setRangeModalVisible(false)}
tabIndex={0}
>
<SVGIcon name="close" />
</div>
@ -314,6 +324,7 @@ export const LinkEditCard: React.FC<LinkCardProps> = ({
<div
className="fortune-link-modify-cell-selector"
onClick={() => setRangeModalVisible(true)}
tabIndex={0}
>
<SVGIcon name="border-all" />
</div>

View File

@ -1,74 +1,74 @@
label {
cursor: default;
cursor: default;
}
#fortune-location-condition {
min-width: 500px;
min-width: 500px;
}
#fortune-location-condition .title {
background-color: #fff;
color: #000;
cursor: default;
font-size: 16px;
font-weight: normal;
line-height: 48px;
background-color: #fff;
color: #000;
cursor: default;
font-size: 16px;
font-weight: normal;
line-height: 48px;
}
#fortune-location-condition .listbox {
border: 1px solid #dfdfdf;
padding: 10px;
font-size: 14px;
color: #000;
border: 1px solid #dfdfdf;
padding: 10px;
font-size: 14px;
color: #000;
}
#fortune-location-condition .listbox .listItem {
padding: 5px 0;
padding: 5px 0;
}
#fortune-location-condition .listbox .listItem input[type="radio"] {
float: left;
margin-top: 5px;
float: left;
margin-top: 5px;
}
#fortune-location-condition .listItem {
padding: 5px 0;
padding: 5px 0;
}
#fortune-location-condition .listItem .subItem {
height: 30px;
padding: 0 10px;
display: block;
height: 30px;
padding: 0 10px;
display: block;
}
#fortune-location-condition input[type="radio"] {
float: left;
margin-top: 3px;
float: left;
margin-top: 3px;
}
#fortune-location-condition .listbox .listItem .subbox {
height: 30px;
padding: 0 10px;
height: 30px;
padding: 0 10px;
}
#fortune-location-condition .listbox .listItem .subbox .subItem {
float: left;
margin-right: 5px;
float: left;
margin-right: 5px;
}
#fortune-location-condition .button-basic {
display: inline-block;
margin-bottom: 0;
font-weight: 400;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
white-space: nowrap;
padding: 4px 8px;
font-size: 14px;
line-height: 1.42857143;
border-radius: 2px;
user-select: none;
margin-top: 10px;
display: inline-block;
margin-bottom: 0;
font-weight: 400;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
white-space: nowrap;
padding: 4px 8px;
font-size: 14px;
line-height: 1.42857143;
border-radius: 2px;
user-select: none;
margin-top: 10px;
}
#fortune-location-condition .button-primary {
background: #0188fb;
border: 1px solid #0188fb;
color: #fff;
margin-right: 10px;
background: #0188fb;
border: 1px solid #0188fb;
color: #fff;
margin-right: 10px;
}
#fortune-location-condition .button-close {
color: #333;
background-color: #fff;
border: 1px solid #ccc;
}
color: #333;
background-color: #fff;
border: 1px solid #ccc;
}

View File

@ -264,6 +264,7 @@ export const LocationCondition: React.FC<{}> = () => {
hideDialog();
onConfirm();
}}
tabIndex={0}
>
{button.confirm}
</div>
@ -272,6 +273,7 @@ export const LocationCondition: React.FC<{}> = () => {
onClick={() => {
hideDialog();
}}
tabIndex={0}
>
{button.cancel}
</div>

View File

@ -26,8 +26,8 @@
}
#fortune-search-replace .tabBox span.on {
background-color: #8C89FE;
border-color: #726EFE;
background-color: #8c89fe;
border-color: #726efe;
color: #fff;
}
@ -129,7 +129,7 @@
}
#fortune-search-replace #searchAllbox .boxMain .boxItem.on {
background-color: #8C89FE;
background-color: #8c89fe;
color: #fff;
}
@ -158,4 +158,4 @@
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -81,6 +81,7 @@ const SearchReplace: React.FC<{
<div
className="icon-close fortune-modal-dialog-icon-close"
onClick={closeDialog}
tabIndex={0}
>
<SVGIcon name="close" style={{ padding: 7, cursor: "pointer" }} />
</div>
@ -89,6 +90,7 @@ const SearchReplace: React.FC<{
id="searchTab"
className={showReplace ? "" : "on"}
onClick={() => setShowReplace(false)}
tabIndex={0}
>
{findAndReplace.find}
</span>
@ -96,6 +98,7 @@ const SearchReplace: React.FC<{
id="replaceTab"
className={showReplace ? "on" : ""}
onClick={() => setShowReplace(true)}
tabIndex={0}
>
{findAndReplace.replace}
</span>
@ -170,6 +173,7 @@ const SearchReplace: React.FC<{
showAlert(alertMsg);
});
}}
tabIndex={0}
>
{findAndReplace.allReplaceBtn}
</div>
@ -190,6 +194,7 @@ const SearchReplace: React.FC<{
}
})
}
tabIndex={0}
>
{findAndReplace.replaceBtn}
</div>
@ -207,6 +212,7 @@ const SearchReplace: React.FC<{
if (_.isEmpty(res)) showAlert(findAndReplace.noFindTip);
})
}
tabIndex={0}
>
{findAndReplace.allFindBtn}
</div>
@ -220,6 +226,7 @@ const SearchReplace: React.FC<{
if (alertMsg != null) showAlert(alertMsg);
})
}
tabIndex={0}
>
{findAndReplace.findBtn}
</div>
@ -228,6 +235,7 @@ const SearchReplace: React.FC<{
<div
className="close-button fortune-message-box-button button-default"
onClick={closeDialog}
tabIndex={0}
>
{button.close}
</div>
@ -261,6 +269,7 @@ const SearchReplace: React.FC<{
});
setSelectedCell({ r: v.r, c: v.c });
}}
tabIndex={0}
>
<span>{v.sheetName}</span>
<span>{v.cellPosition}</span>

Some files were not shown because too many files have changed in this diff Show More