Compare commits
51 Commits
18f8739fd7
...
master
Author | SHA1 | Date | |
---|---|---|---|
dd31045338 | |||
291f011226 | |||
bbcd2050e7 | |||
1162664263 | |||
32066ad187 | |||
1ae21ed665 | |||
c7ad5298af | |||
76cff0e692 | |||
b5aa365324 | |||
c25ec21d5a | |||
59ed696163 | |||
51fe00060b | |||
6d51a10a2a | |||
dd94095bcf | |||
f1ced3dacf | |||
cacdcae9e0 | |||
4bdc6354d8 | |||
1f63b6ccb6 | |||
0dab4976ae | |||
dab2b9a852 | |||
ed93abeef4 | |||
092e84d8bb | |||
141c698351 | |||
9a62bd2905 | |||
476aec75b4 | |||
c9e419d8e9 | |||
7939aaf3a7 | |||
94f7ec85e9 | |||
3cca634101 | |||
82ca2e8a3e | |||
482cebe73a | |||
7c95a0758f | |||
01be6cede8 | |||
64f273a6ae | |||
556645844d | |||
8eb807714c | |||
d8ee6074fa | |||
c5aef0a81e | |||
af709965c5 | |||
9f41d623e4 | |||
0932891b20 | |||
33597eb4e9 | |||
42961836ba | |||
dc1e0cf0bd | |||
9f10af6d0e | |||
84ef0f7bc7 | |||
01d90058ab | |||
99fc79d312 | |||
29a023b32b | |||
f4f77630d7 | |||
2d943894c1 |
14
.drone.yml
Normal file
14
.drone.yml
Normal file
@ -0,0 +1,14 @@
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: setup
|
||||
image: registry:5000/node-build
|
||||
commands:
|
||||
- yarn
|
||||
- curl https://git.scode.ovh/Timo/standard/raw/branch/master/ci.js > ci.js
|
||||
|
||||
- name: build
|
||||
image: registry:5000/node-build
|
||||
commands:
|
||||
- node ci.js
|
27
CHANGELOG.md
Normal file
27
CHANGELOG.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## 1.8.0
|
||||
|
||||
custom filter functions
|
||||
|
||||
## 1.7.0
|
||||
|
||||
carry values between filter runs
|
||||
|
||||
## 1.6.0
|
||||
|
||||
filter groups
|
||||
|
||||
## 1.5.0
|
||||
|
||||
filter over multiple fields
|
||||
|
||||
## 1.4.0
|
||||
|
||||
function to filter arrays of objects recursively
|
||||
|
||||
## 1.1.0 - 1.3.0 (lost changelog)
|
||||
|
||||
## 1.0.0
|
||||
|
||||
initial release
|
23
Jenkinsfile
vendored
23
Jenkinsfile
vendored
@ -1,23 +0,0 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
VERSION = VersionNumber([
|
||||
versionNumberString:
|
||||
'${BUILDS_ALL_TIME}',
|
||||
versionPrefix: '1.3.',
|
||||
worstResultForIncrement: 'SUCCESS'
|
||||
])
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Building') {
|
||||
steps {
|
||||
script {
|
||||
currentBuild.displayName = env.VERSION
|
||||
}
|
||||
sh 'yarn ci ${VERSION}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
161
README.md
161
README.md
@ -1,6 +1,6 @@
|
||||
# @sapphirecode/utilities
|
||||
|
||||
version: 1.3.x
|
||||
version: 1.8.x
|
||||
|
||||
small utility functions to make much needed features easier to work with
|
||||
|
||||
@ -12,34 +12,49 @@ npm:
|
||||
|
||||
yarn:
|
||||
|
||||
> yarn add @sapphirecode/utilities
|
||||
> yarn add @sapphirecode/utilities
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const util = require('@sapphirecode/utilities');
|
||||
```
|
||||
|
||||
// cut off decimal places to a specified point
|
||||
cut off decimal places to a specified point
|
||||
|
||||
```js
|
||||
util.truncate_decimal(12.345678, 2);
|
||||
// returns 12.34
|
||||
```
|
||||
|
||||
// will return null instead of throwing on invalid json
|
||||
will return null instead of throwing on invalid json
|
||||
|
||||
```js
|
||||
util.try_parse_json('{{foo');
|
||||
```
|
||||
|
||||
// copy an object to prevent modification of the original
|
||||
const obj = {foo:'bar'};
|
||||
copy an object to prevent modification of the original
|
||||
|
||||
```js
|
||||
const obj = {foo: 'bar'};
|
||||
const copy = util.copy_object(obj);
|
||||
copy.foo = 'baz';
|
||||
console.log(obj.foo); // bar
|
||||
```
|
||||
|
||||
// run a regular expression and get a callback for every result
|
||||
const data = "foobarfoo";
|
||||
run a regular expression and get a callback for every result
|
||||
|
||||
```js
|
||||
const data = 'foobarfoo';
|
||||
const regex = /foo/g;
|
||||
util.run_regex(regex, data, res => {
|
||||
util.run_regex(regex, data, (res) => {
|
||||
console.log(res[0]); // will output 'foo' 2 times
|
||||
});
|
||||
```
|
||||
|
||||
// check if a variable is null, undefined or NaN
|
||||
check if a variable is null, undefined or NaN
|
||||
|
||||
```js
|
||||
console.log(util.is_nil(parseInt('abc'))); // true
|
||||
console.log(util.is_nil('foo')); // false
|
||||
console.log(util.is_nil(42)); // false
|
||||
@ -47,6 +62,132 @@ console.log(util.is_nil(null)); // true
|
||||
console.log(util.is_nil(undefined)); // true
|
||||
```
|
||||
|
||||
filter an array recursively
|
||||
|
||||
```js
|
||||
const to_filter = [
|
||||
{name: 'include_foo'},
|
||||
{
|
||||
name: 'include_bar',
|
||||
children: [{name: 'foo'}, {name: 'bar'}],
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
children: [{name: 'include_foo'}, {name: 'bar'}],
|
||||
},
|
||||
{
|
||||
name: 'barbaz',
|
||||
children: [{name: 'foo'}, {name: 'bar'}],
|
||||
},
|
||||
];
|
||||
const filter = {
|
||||
field: 'name', // the field the filter will apply on
|
||||
filter: /^include_.*/iu, // regex filter
|
||||
};
|
||||
|
||||
const result = util.recursive_filter(
|
||||
to_filter,
|
||||
[filter], // you can specify multiple filters, they will be connected using AND
|
||||
'children' // specify which field an objects children are stored in ('children' is default)
|
||||
);
|
||||
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
/* output:
|
||||
|
||||
[
|
||||
{ name: 'include_foo' },
|
||||
{
|
||||
name: 'include_bar',
|
||||
children: [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
children: [ { name: 'include_foo' } ]
|
||||
}
|
||||
]*/
|
||||
```
|
||||
|
||||
filters can also apply to multiple fields
|
||||
|
||||
```js
|
||||
const result = util.recursive_filter(
|
||||
[{name: 'foo', name_2: 'bar'}],
|
||||
[
|
||||
{
|
||||
filter: /foo bar/iu,
|
||||
field: ['name', 'name_2'], // fields will be joined with a space in between
|
||||
// {name: 'foo', name_2: 'bar'} will become 'foo bar'
|
||||
},
|
||||
]
|
||||
);
|
||||
```
|
||||
|
||||
filter groups can be used to connect filters with OR
|
||||
|
||||
```js
|
||||
const result = util.recursive_filter(
|
||||
[...],
|
||||
[
|
||||
{
|
||||
filter: /foo bar/iu,
|
||||
field: 'name'
|
||||
},
|
||||
{
|
||||
or: [
|
||||
{ filter: /foo/u, field: 'bar' },
|
||||
{ filter: /bar/u, field: 'bar' }
|
||||
]
|
||||
}
|
||||
]
|
||||
);
|
||||
```
|
||||
|
||||
field values can be carried to filter runs on children to filter over the entire tree instead of just one element
|
||||
|
||||
```js
|
||||
const to_filter = [
|
||||
{
|
||||
name: 'foo',
|
||||
children: [
|
||||
{ name: 'bar' },
|
||||
{ name: 'baz' },
|
||||
{ foo: 'bar' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const res = util.recursive_filter (
|
||||
to_filter,
|
||||
[ { field: 'name', filter: /foo bar/ui } ], // values will be separaed by a space
|
||||
'children',
|
||||
[ 'name' ] // specify which fields should be carried
|
||||
// the filters will receive the carried values instead of the plain fields
|
||||
);
|
||||
|
||||
/* result:
|
||||
|
||||
[
|
||||
{
|
||||
name: 'foo',
|
||||
children: [ { name: 'bar' } ]
|
||||
}
|
||||
]
|
||||
*/
|
||||
```
|
||||
|
||||
custom functions to match items can also be used
|
||||
|
||||
```js
|
||||
const filter = {
|
||||
function: (element) => {
|
||||
return element.should_match;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT © Timo Hocker <timo@scode.ovh>
|
||||
|
121
filter.js
Normal file
121
filter.js
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||
* This file is part of utilities which is released under MIT.
|
||||
* See file 'LICENSE' for full license details.
|
||||
* Created by Timo Hocker <timo@scode.ovh>, November 2020
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function get_element_field (element, carried_data, field) {
|
||||
if (typeof carried_data[field] !== 'undefined')
|
||||
return carried_data[field];
|
||||
return element[field];
|
||||
}
|
||||
|
||||
function check_filter (filter, e, carried_data) {
|
||||
if (typeof filter.function !== 'undefined')
|
||||
return filter.function ({ ...e, ...carried_data });
|
||||
|
||||
const search_str = Array.isArray (filter.field)
|
||||
? filter.field.map ((f) => get_element_field (e, carried_data, f))
|
||||
.filter ((v) => typeof v !== 'undefined')
|
||||
.join (' ')
|
||||
: get_element_field (e, carried_data, filter.field);
|
||||
|
||||
return filter.filter.test (search_str);
|
||||
}
|
||||
|
||||
function check_filters (filters, e, carried_data, or = false) {
|
||||
for (const filter of filters) {
|
||||
let res = false;
|
||||
if (Array.isArray (filter.or))
|
||||
res = check_filters (filter.or, e, carried_data, true);
|
||||
else
|
||||
res = check_filter (filter, e, carried_data);
|
||||
|
||||
if (or && res)
|
||||
return true;
|
||||
if (!res && !or)
|
||||
return false;
|
||||
}
|
||||
return !or;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef Filter
|
||||
* @type {object}
|
||||
* @property {string|string[]} field - fields to apply filter on
|
||||
* @property {RegExp} filter - filter
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef FilterFunction
|
||||
* @type {object}
|
||||
* @property {function} function - function to test element for match
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef FilterOrGroup
|
||||
* @type {object}
|
||||
* @property {FilterType[]} or - create an OR group of filters
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef FilterType
|
||||
* @type {Filter|FilterFunction|FilterOrGroup}
|
||||
*/
|
||||
|
||||
/**
|
||||
* filter nested objects
|
||||
*
|
||||
* @param {Array<object>} input object to filter
|
||||
* @param {FilterType[]} filters filters
|
||||
* @param {string[]} carry carry data to children to match
|
||||
* @param {object} carried_data internal: carried data
|
||||
* @returns {Array<object>} filtered data
|
||||
*/
|
||||
function recursive_filter (
|
||||
input,
|
||||
filters,
|
||||
children_key = 'children',
|
||||
carry = [],
|
||||
carried_data = {}
|
||||
) {
|
||||
const data = [ ...input ];
|
||||
const filtered = [];
|
||||
|
||||
for (const c of carry) {
|
||||
if (typeof carried_data[c] !== 'string')
|
||||
carried_data[c] = '';
|
||||
}
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const e = { ...data[i] };
|
||||
data[i] = e;
|
||||
const sub_carry = { ...carried_data };
|
||||
for (const c of carry) {
|
||||
if (typeof e[c] !== 'undefined')
|
||||
sub_carry[c] += `${sub_carry[c].length > 0 ? ' ' : ''}${e[c]}`;
|
||||
}
|
||||
if (check_filters (filters, e, sub_carry)) {
|
||||
filtered.push (e);
|
||||
}
|
||||
else {
|
||||
if (typeof e[children_key] === 'undefined')
|
||||
continue;
|
||||
e[children_key] = recursive_filter (
|
||||
e[children_key],
|
||||
filters,
|
||||
children_key,
|
||||
carry,
|
||||
sub_carry
|
||||
);
|
||||
if (e[children_key].length > 0)
|
||||
filtered.push (e);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
module.exports = recursive_filter;
|
44
index.d.ts
vendored
44
index.d.ts
vendored
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||
* This file is part of utilities which is released under MIT.
|
||||
* See file 'LICENSE' for full license details.
|
||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||
*/
|
||||
|
||||
/**
|
||||
* truncates a floating point number
|
||||
*
|
||||
* @param {number} num number to truncate
|
||||
* @param {number} len length to truncate to
|
||||
* @returns {number} truncated number
|
||||
*/
|
||||
export function truncate_decimal(num: number, len: number): number;
|
||||
/**
|
||||
* parse json and catch invalid strings
|
||||
*
|
||||
* @param {string} text input
|
||||
* @returns {any} parsed
|
||||
*/
|
||||
export function try_parse_json(text: string): any;
|
||||
/**
|
||||
* copy an object to prevent modification to the original
|
||||
*
|
||||
* @param {object} obj object to copy
|
||||
* @returns {object} copy
|
||||
*/
|
||||
export function copy_object(obj: any): any;
|
||||
/**
|
||||
* run a regular expression and callback for every result
|
||||
*
|
||||
* @param {any} regex regular expression
|
||||
* @param {any} data data to run on
|
||||
* @param {any} func function to execute
|
||||
*/
|
||||
export function run_regex(regex: any, data: any, func: any): void;
|
||||
/**
|
||||
* check if an object is either undefined, null or NaN
|
||||
*
|
||||
* @param {any} obj object to check
|
||||
* @returns {boolean} true if nil
|
||||
*/
|
||||
export function is_nil(obj: any): boolean;
|
5
index.js
5
index.js
@ -7,6 +7,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const recursive_filter = require ('./filter');
|
||||
|
||||
/**
|
||||
* truncates a floating point number
|
||||
*
|
||||
@ -83,5 +85,6 @@ module.exports = {
|
||||
try_parse_json,
|
||||
copy_object,
|
||||
run_regex,
|
||||
is_nil
|
||||
is_nil,
|
||||
recursive_filter
|
||||
};
|
||||
|
14
jasmine.json
Normal file
14
jasmine.json
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
{
|
||||
"spec_dir": "test",
|
||||
"spec_files": [
|
||||
"spec/*.js",
|
||||
"spec/*.ts"
|
||||
],
|
||||
"helpers": [
|
||||
"helpers/*.js",
|
||||
"helpers/*.ts"
|
||||
],
|
||||
"stopSpecOnExpectationFailure": false,
|
||||
"random": false
|
||||
}
|
54
jenkins.js
54
jenkins.js
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||
* This file is part of utilities which is released under MIT.
|
||||
* See file 'LICENSE' for full license details.
|
||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require ('fs');
|
||||
const child_process = require ('child_process');
|
||||
|
||||
const pkg = JSON.parse (fs.readFileSync ('package.json', 'utf-8'));
|
||||
[
|
||||
,, pkg.version
|
||||
] = process.argv;
|
||||
fs.writeFileSync ('package.json', JSON.stringify (pkg, null, 2));
|
||||
|
||||
child_process.execSync ('yarn lint', { stdio: 'inherit' });
|
||||
child_process.execSync ('yarn test', { stdio: 'inherit' });
|
||||
child_process.execSync ('yarn compile', { stdio: 'inherit' });
|
||||
|
||||
if (typeof pkg.description === 'undefined' || pkg.description === '') {
|
||||
console.log ('description undefined');
|
||||
process.exit (1);
|
||||
}
|
||||
|
||||
if (typeof pkg.repository === 'undefined') {
|
||||
console.log ('repository undefined');
|
||||
process.exit (1);
|
||||
}
|
||||
|
||||
function major (version) {
|
||||
return version.replace (/\.[0-9]+$/ui, '');
|
||||
}
|
||||
|
||||
if (fs.existsSync ('README.md')) {
|
||||
const readme = fs.readFileSync ('README.md', 'utf-8');
|
||||
const version = (/version: ([0-9.]+)/ui).exec (readme);
|
||||
if (
|
||||
version === null
|
||||
|| major (version[1]) !== major (pkg.version)
|
||||
) {
|
||||
console.log ('readme version does not match package version');
|
||||
process.exit (1);
|
||||
}
|
||||
else { child_process.execSync ('yarn publish --access public'); }
|
||||
}
|
||||
else {
|
||||
console.log ('readme does not exist');
|
||||
process.exit (1);
|
||||
}
|
34
package.json
34
package.json
@ -1,37 +1,45 @@
|
||||
{
|
||||
"name": "@sapphirecode/utilities",
|
||||
"version": "1.0.0",
|
||||
"version": "1.8.8",
|
||||
"main": "index.js",
|
||||
"author": "Timo Hocker <timo@scode.ovh>",
|
||||
"author": {
|
||||
"name": "Timo Hocker",
|
||||
"email": "timo@scode.ovh"
|
||||
},
|
||||
"bugs": "https://redmine.scode.ovh/projects/utilities",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"utilities",
|
||||
"regex",
|
||||
"json"
|
||||
"json",
|
||||
"filters"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.scode.ovh:timo/utilities"
|
||||
"url": "https://git.scode.ovh:timo/utilities.git"
|
||||
},
|
||||
"description": "small utility functions to make much needed features easier to work with",
|
||||
"devDependencies": {
|
||||
"@sapphirecode/eslint-config": "^2.1.3",
|
||||
"@stryker-mutator/core": "^3.2.1",
|
||||
"@stryker-mutator/javascript-mutator": "^3.2.1",
|
||||
"ava": "^3.8.2",
|
||||
"@stryker-mutator/core": "^5.0.0",
|
||||
"@stryker-mutator/jasmine-runner": "^5.0.0",
|
||||
"@types/jasmine": "^3.5.14",
|
||||
"eslint": "^7.0.0",
|
||||
"jasmine": "^3.6.1",
|
||||
"nyc": "^15.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.mjs",
|
||||
"test": "nyc ava",
|
||||
"ci": "yarn && node jenkins.js",
|
||||
"test": "nyc jasmine --config=\"jasmine.json\"",
|
||||
"mutate": "stryker run",
|
||||
"compile": "tsc --allowJs --declaration --emitDeclarationOnly index.js"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
]
|
||||
}
|
||||
"*.js",
|
||||
"*.d.ts"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,19 @@
|
||||
* @type {import('@stryker-mutator/api/core').StrykerOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
mutator: 'javascript',
|
||||
packageManager: 'yarn',
|
||||
reporters: [
|
||||
'clear-text',
|
||||
'progress'
|
||||
],
|
||||
testRunner: 'command',
|
||||
transpilers: [],
|
||||
coverageAnalysis: 'all',
|
||||
mutate: [ 'index.js' ]
|
||||
testRunner: 'jasmine',
|
||||
jasmineConfigFile: 'jasmine.json',
|
||||
coverageAnalysis: 'perTest',
|
||||
mutate: [
|
||||
'**/*.js',
|
||||
'**/*.ts',
|
||||
'!**/test/**/*',
|
||||
'!**/spec/**/*',
|
||||
'!stryker.conf.js'
|
||||
]
|
||||
};
|
||||
|
102
test/index.js
102
test/index.js
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||
* This file is part of utilities which is released under MIT.
|
||||
* See file 'LICENSE' for full license details.
|
||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||
*/
|
||||
|
||||
/* eslint-disable no-magic-numbers */
|
||||
// @ts-nocheck
|
||||
'use strict';
|
||||
|
||||
const test = require ('ava');
|
||||
const util = require ('../index');
|
||||
|
||||
test ('truncate_decimal', (t) => {
|
||||
const trunc = util.truncate_decimal (1.23456, 2);
|
||||
t.is (trunc, 1.23);
|
||||
});
|
||||
|
||||
test ('try_parse_json should parse', (t) => {
|
||||
const str = '{"test":"foo"}';
|
||||
t.notThrows (() => {
|
||||
const json = util.try_parse_json (str);
|
||||
t.deepEqual (json, { test: 'foo' });
|
||||
});
|
||||
});
|
||||
|
||||
test ('try_parse_json should fail', (t) => {
|
||||
const str = '{"test":foo"}';
|
||||
t.notThrows (() => {
|
||||
const json = util.try_parse_json (str);
|
||||
t.is (json, null);
|
||||
});
|
||||
});
|
||||
|
||||
test ('copy object', (t) => {
|
||||
const obj = { foo: 'bar' };
|
||||
const copy = util.copy_object (obj);
|
||||
copy.foo = 'baz';
|
||||
t.is (copy.foo, 'baz');
|
||||
t.is (obj.foo, 'bar');
|
||||
});
|
||||
|
||||
test ('run regex', (t) => {
|
||||
const data = 'foobarfoo';
|
||||
const regex = /foo/gu;
|
||||
let count = 0;
|
||||
util.run_regex (regex, data, (res) => {
|
||||
t.is (res[0], 'foo');
|
||||
count++;
|
||||
});
|
||||
t.is (count, 2);
|
||||
});
|
||||
|
||||
test ('run non-global regex', (t) => {
|
||||
const data = 'foobarfoo';
|
||||
const regex = /foo/u;
|
||||
let count = 0;
|
||||
util.run_regex (regex, data, (res) => {
|
||||
t.is (res[0], 'foo');
|
||||
count++;
|
||||
});
|
||||
t.is (count, 1);
|
||||
});
|
||||
|
||||
test ('run non-global regex without result', (t) => {
|
||||
const data = 'foobarfoo';
|
||||
const regex = /baz/u;
|
||||
let count = 0;
|
||||
util.run_regex (regex, data, () => {
|
||||
count++;
|
||||
});
|
||||
t.is (count, 0);
|
||||
});
|
||||
|
||||
test ('check isnil with undefined', (t) => {
|
||||
t.is (util.is_nil (), true);
|
||||
});
|
||||
|
||||
test ('check isnil with null', (t) => {
|
||||
t.is (util.is_nil (null), true);
|
||||
});
|
||||
|
||||
test ('check isnil with empty string', (t) => {
|
||||
t.is (util.is_nil (''), false);
|
||||
});
|
||||
|
||||
test ('check isnil with string', (t) => {
|
||||
t.is (util.is_nil ('foo'), false);
|
||||
});
|
||||
|
||||
test ('check isnil with 0', (t) => {
|
||||
t.is (util.is_nil (0), false);
|
||||
});
|
||||
|
||||
test ('check isnil with nan', (t) => {
|
||||
t.is (util.is_nil (parseInt ('foo')), true);
|
||||
});
|
||||
|
||||
test ('check isnil with int', (t) => {
|
||||
t.is (util.is_nil (parseInt ('42')), false);
|
||||
});
|
309
test/spec/index.js
Normal file
309
test/spec/index.js
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||
* This file is part of utilities which is released under MIT.
|
||||
* See file 'LICENSE' for full license details.
|
||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
'use strict';
|
||||
|
||||
const util = require ('../../index');
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
describe ('utilities', () => {
|
||||
it ('should truncate_decimal', () => {
|
||||
const trunc = util.truncate_decimal (1.23456, 2);
|
||||
expect (trunc)
|
||||
.toEqual (1.23);
|
||||
});
|
||||
|
||||
it ('try_parse_json should parse', () => {
|
||||
const str = '{"test":"foo"}';
|
||||
expect (() => {
|
||||
const json = util.try_parse_json (str);
|
||||
expect (json)
|
||||
.toEqual ({ test: 'foo' });
|
||||
}).not.toThrow ();
|
||||
});
|
||||
|
||||
it ('try_parse_json should fail', () => {
|
||||
const str = '{"test":foo"}';
|
||||
expect (() => {
|
||||
const json = util.try_parse_json (str);
|
||||
expect (json)
|
||||
.toBeNull ();
|
||||
}).not.toThrow ();
|
||||
});
|
||||
|
||||
it ('should copy object', () => {
|
||||
const obj = { foo: 'bar', bar: { foo: 'baz' } };
|
||||
const copy = util.copy_object (obj);
|
||||
expect (obj).not.toBe (copy);
|
||||
expect (obj)
|
||||
.toEqual (copy);
|
||||
copy.foo = 'baz';
|
||||
copy.bar.foo = 'bar';
|
||||
expect (copy.foo)
|
||||
.toEqual ('baz');
|
||||
expect (copy.bar.foo)
|
||||
.toEqual ('bar');
|
||||
expect (obj.foo)
|
||||
.toEqual ('bar');
|
||||
expect (obj.bar.foo)
|
||||
.toEqual ('baz');
|
||||
});
|
||||
|
||||
it ('should run regex', () => {
|
||||
const data = 'foobarfoo';
|
||||
const regex = /foo/gu;
|
||||
let count = 0;
|
||||
util.run_regex (regex, data, (res) => {
|
||||
expect (res[0])
|
||||
.toEqual ('foo');
|
||||
count++;
|
||||
});
|
||||
expect (count)
|
||||
.toEqual (2);
|
||||
});
|
||||
|
||||
it ('should run non-global regex', () => {
|
||||
const data = 'foobarfoo';
|
||||
const regex = /foo/u;
|
||||
let count = 0;
|
||||
util.run_regex (regex, data, (res) => {
|
||||
expect (res[0])
|
||||
.toEqual ('foo');
|
||||
count++;
|
||||
});
|
||||
expect (count)
|
||||
.toEqual (1);
|
||||
});
|
||||
|
||||
it ('should run non-global regex without result', () => {
|
||||
const data = 'foobarfoo';
|
||||
const regex = /baz/u;
|
||||
let count = 0;
|
||||
util.run_regex (regex, data, () => {
|
||||
count++;
|
||||
});
|
||||
expect (count)
|
||||
.toEqual (0);
|
||||
});
|
||||
|
||||
it ('should check isnil with undefined', () => {
|
||||
expect (util.is_nil ())
|
||||
.toEqual (true);
|
||||
});
|
||||
|
||||
it ('should check isnil with null', () => {
|
||||
expect (util.is_nil (null))
|
||||
.toEqual (true);
|
||||
});
|
||||
|
||||
it ('should check isnil with empty string', () => {
|
||||
expect (util.is_nil (''))
|
||||
.toEqual (false);
|
||||
});
|
||||
|
||||
it ('should check isnil with string', () => {
|
||||
expect (util.is_nil ('foo'))
|
||||
.toEqual (false);
|
||||
});
|
||||
|
||||
it ('should check isnil with 0', () => {
|
||||
expect (util.is_nil (0))
|
||||
.toEqual (false);
|
||||
});
|
||||
|
||||
it ('should check isnil with nan', () => {
|
||||
expect (util.is_nil (parseInt ('foo')))
|
||||
.toEqual (true);
|
||||
});
|
||||
|
||||
it ('should check isnil with int', () => {
|
||||
expect (util.is_nil (parseInt ('42')))
|
||||
.toEqual (false);
|
||||
});
|
||||
|
||||
it ('recursive filter', () => {
|
||||
const raw = [
|
||||
{ name: 'include_foo' },
|
||||
{
|
||||
name: 'include_bar',
|
||||
children: [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
children: [
|
||||
{ name: 'include_foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'barbaz',
|
||||
children: [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
}
|
||||
];
|
||||
const filtered = [
|
||||
{ name: 'include_foo' },
|
||||
{
|
||||
name: 'include_bar',
|
||||
children: [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
children: [ { name: 'include_foo' } ]
|
||||
}
|
||||
];
|
||||
const filter = {
|
||||
field: 'name',
|
||||
filter: /^include_.*/ui
|
||||
};
|
||||
const result = util.recursive_filter (raw, [ filter ]);
|
||||
expect (filtered)
|
||||
.toEqual (result);
|
||||
});
|
||||
|
||||
it ('recursive filter multifield', () => {
|
||||
const raw = [
|
||||
{ name: 'foo', f: 'include' },
|
||||
{
|
||||
name: 'include_bar',
|
||||
children: [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
children: [
|
||||
{ name: 'include_foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'barbaz',
|
||||
children: [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' }
|
||||
]
|
||||
}
|
||||
];
|
||||
const filtered = [ { name: 'foo', f: 'include' } ];
|
||||
const filter = {
|
||||
field: [
|
||||
'name',
|
||||
'f'
|
||||
],
|
||||
filter: /foo include/ui
|
||||
};
|
||||
const result = util.recursive_filter (raw, [ filter ]);
|
||||
expect (filtered)
|
||||
.toEqual (result);
|
||||
});
|
||||
|
||||
it ('recursive filter undefined multifield', () => {
|
||||
const res = util.recursive_filter (
|
||||
[ { foo: 'bar' } ],
|
||||
[
|
||||
{
|
||||
field: [
|
||||
'foo',
|
||||
'bar'
|
||||
],
|
||||
filter: /\s/u
|
||||
}
|
||||
]
|
||||
);
|
||||
expect (res)
|
||||
.toEqual ([]);
|
||||
});
|
||||
|
||||
it ('recursive filter with or group', () => {
|
||||
const to_filter = [
|
||||
{ name: 'foo' },
|
||||
{ name: 'bar' },
|
||||
{ name: 'baz' }
|
||||
];
|
||||
|
||||
const filter = [
|
||||
{
|
||||
or: [
|
||||
{ field: 'name', filter: /foo/u },
|
||||
{ field: 'name', filter: /bar/u }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const res = util.recursive_filter (to_filter, filter);
|
||||
|
||||
expect (res)
|
||||
.toEqual (to_filter.slice (0, 2));
|
||||
});
|
||||
|
||||
it ('recursive filter carry field', () => {
|
||||
const to_filter = [
|
||||
{
|
||||
name: 'foo',
|
||||
children: [
|
||||
{ name: 'bar' },
|
||||
{ name: 'baz' },
|
||||
{ foo: 'bar' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const res = util.recursive_filter (
|
||||
to_filter,
|
||||
[ { field: 'name', filter: /foo bar/ui } ],
|
||||
'children',
|
||||
[ 'name' ]
|
||||
);
|
||||
|
||||
expect (res)
|
||||
.toEqual ([
|
||||
{
|
||||
name: 'foo',
|
||||
children: [ { name: 'bar' } ]
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it ('recursive filter custom function', () => {
|
||||
const to_filter = [
|
||||
{
|
||||
name: 'foo',
|
||||
children: [
|
||||
{ name: 'bar' },
|
||||
{ name: 'baz' },
|
||||
{ foo: 'bar' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const res = util.recursive_filter (
|
||||
to_filter,
|
||||
[ { function: (elem) => elem.name === 'foo bar' } ],
|
||||
'children',
|
||||
[ 'name' ]
|
||||
);
|
||||
|
||||
expect (res)
|
||||
.toEqual ([
|
||||
{
|
||||
name: 'foo',
|
||||
children: [ { name: 'bar' } ]
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user