Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

blork

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

blork - npm Package Compare versions

Comparing version 8.2.0 to 8.3.1

4

lib/checkers/checkers.js

@@ -65,2 +65,3 @@ /* eslint-disable prettier/prettier */

function isRegExp(v) { return v instanceof RegExp; }
function isError(v) { return v instanceof Error; }
function isSymbol(v) { return typeof v === "symbol"; }

@@ -114,2 +115,3 @@ function isAny() { return true; }

isRegExp.desc = "regular expression"
isError.desc = "error"
isSymbol.desc = "symbol"

@@ -193,2 +195,4 @@ isAny.desc = "any"

"regexp": isRegExp,
"err": isError,
"error": isError,
"symbol": isSymbol,

@@ -195,0 +199,0 @@

12

lib/classes/Blorker.js

@@ -21,3 +21,3 @@ const ValueError = require("../errors/ValueError");

// Throw either checker.error or error with standardised message.
throwError(checker.error || error, `Must be ${checker.desc}`, value, prefix);
throwError(checker.error || error, `${checker.prefix || "Must be"} ${checker.desc}`, value, prefix);
}

@@ -104,5 +104,5 @@

// Check args.
runChecker(this.checkers.string, description, "check(): description", BlorkError);
if (prefix) runChecker(this.checkers.string, prefix, "check(): prefix", BlorkError);
if (error) runChecker(this.checkers.function, error, "check(): error", BlorkError);
runChecker(this.checkers.string, description, "assert(): description", BlorkError);
if (prefix) runChecker(this.checkers.string, prefix, "assert(): prefix", BlorkError);
if (error) runChecker(this.checkers.function, error, "assert(): error", BlorkError);

@@ -148,4 +148,4 @@ // Enforce assertion.

runChecker(this.checkers.array, types, "args(): types", BlorkError);
if (prefix) runChecker(this.checkers.string, prefix, "add(): prefix", BlorkError);
if (error) runChecker(this.checkers.function, error, "add(): error", BlorkError);
if (prefix) runChecker(this.checkers.string, prefix, "args(): prefix", BlorkError);
if (error) runChecker(this.checkers.function, error, "args(): error", BlorkError);

@@ -152,0 +152,0 @@ // Recurse into each type.

@@ -32,5 +32,10 @@ const format = require("../helpers/format");

if (frame) {
// Prepend the caller function name to the prefix, e.g. "name" → "MyClass.myFunc(): name"
/* istanbul ignore else */
if (frame.function) prefix = prefix ? `${frame.function}: ${prefix}` : frame.function;
// Was this not called by an anonymous function?
if (frame.function) {
// Prepend the calling function name to the prefix, e.g. "name" → "MyClass.myFunc(): name"
if (!prefix) prefix = frame.function;
else if (prefix.indexOf(": ") === -1)
// Skip any prefixes that already have a ':' colon.
prefix = `${frame.function}: ${prefix}`;
}
// Update file, line, column.

@@ -37,0 +42,0 @@ this.fileName = frame.file;

@@ -22,18 +22,28 @@ const destack = require("./destack");

// Loop through the frames (stop at end-minus-1 because we need there to be a next frame).
for (let i = 0; i < frames.length - 2; i++) {
// Remove this frame from the lines.
const j = lines.indexOf(frames[i].original);
/* istanbul ignore else */
if (j >= 0) lines.splice(j, 1);
// Whether to return the next frame in the loop with a named function.
let returnNextNamed = false;
// Loop through the frames.
for (let i = 0; i < frames.length; i++) {
// Does the function name include "Blorker$"
if (frames[i].function.indexOf("Blorker$") >= 0) {
// Return NEXT frame (with a recombined stack property)
return Object.assign({ stack: lines.join("\n") }, frames[i + 1]);
// Return the next named function.
returnNextNamed = true;
} else if (returnNextNamed && frames[i].function) {
// Return this frame (if the previous frame had a function named Blorker$etc and this frame has a named function).
// Recreate the stack property ignoring all lines above this.
frames[i].stack = lines.join("\n");
// Return this frame.
return frames[i];
}
// Remove this line from the stack.
const j = lines.indexOf(frames[i].original);
/* istanbul ignore else */
if (j >= 0) lines.splice(j, 1);
}
// Otherwise return the first frame.
return Object.assign({ stack: stack }, frames[0]);
frames[0].stack = stack;
return frames[0];
}

@@ -40,0 +50,0 @@ }

@@ -376,2 +376,3 @@ const debug = require("../helpers/debug");

checker.desc = number.toString();
checker.string = number.toString();

@@ -433,3 +434,23 @@ // Return the checker.

}
},
// Return type.
// Changes error message from e.g. "Must be string" to "Must return string"
{
start: "return ",
callback(type, find) {
// Get normal checker.
const valueChecker = find(type);
// Create a checker.
const checker = v => valueChecker(v);
// Checker settings.
checker.desc = valueChecker.desc;
checker.prefix = "Must return";
// Return it.
return checker;
}
}
];
{
"name": "blork",
"description": "Blork! Mini runtime type checking in Javascript",
"version": "8.2.0",
"version": "8.3.1",
"license": "0BSD",

@@ -25,2 +25,3 @@ "author": "Dave Houlbrooke <dave@shax.com>",

"watch": "jest --watchAll",
"jest": "jest --coverage",
"test": "jest --coverage",

@@ -27,0 +28,0 @@ "lint": "eslint ./",

@@ -17,4 +17,39 @@ # Blork! Mini runtime type checking in Javascript

## Usage
## Canonical example
The perfect use case for Blork is where you need to validate the input for a library function in a neat and clear way — with error messages that actually help developers fix the mistake!
```js
// findStrings.js
import { check } from "blork";
// 1. Make a function that needs its arguments validated.
function findStrings(haystack, needles, startIndex = 0, caseSensitive = false) {
// Check the args.
check(haystack, "str", "haystack"); // Must be string.
check(needles, "str+|str+[]+", "needles"); // Must be non-empty string or non-empty array of non-empty strings.
check(startIndex, "int{1,}", "startIndex"); // Must be integer greater than 1.
check(caseSensitive, "bool", "caseSensitive"); // Must be boolean true or false.
// ...etc
return etc;
}
// 2. Call the function we made with valid arguments.
const sentence = "These dogs and cats are the best.";
const finds = findStrings(sentence, ["dogs", "cats", "best"], 6, true);
// 3. Call the function with invalid arguments.
// This will throw TypeError "findStrings(): haystack: Must be string (received 1234)"
const nope1 = findStrings(1234);
// This will throw TypeError "findStrings(): needles: Must be non-empty array containing non-empty string (received ["dogs", 1234])"
const nope1 = findStrings("Nopes", ["dogs", 1234]);
// This will throw TypeError "findStrings(): startIndex: Must be integer (minimum 1) (received 0)"
const nope2 = findStrings("Nopes", ["dogs"], 0);
// This will throw TypeError "findStrings(): caseSensitive: Must be boolean (received null)"
const nope2 = findStrings("Nopes", ["dogs"], 0, null);
```
## Usage guide
### check(): Check individual values

@@ -58,2 +93,3 @@

- Appending a `+` means non-empty (e.g. `arr+` `str+` means non-empty arrays and strings respectively).
- ...and many more

@@ -96,7 +132,7 @@ ```js

check([1, "a"], "[int, str]"); // No error.
check([1, false], "[int, str]"); // Throws ValueError "Must be plain array tuple containing integer, string (received [1, false])"
check([1, false], "[int, str]"); // Throws ValueError "Must be plain array tuple like [integer, string] (received [1, false])"
// Object types.
check({ a: 1 }, "{ camel: integer }"); // No error.
check({ "$": 1 }, "{ camel: integer }"); // Throws ValueError "Must be plain object with camelCase string keys containing integer (received { "$": 1 })"
check({ "$": 1 }, "{ camel: integer }"); // Throws ValueError "Must be plain object like { camelCase string: integer } (received { "$": 1 })"

@@ -428,2 +464,3 @@ // String literal types.

| `regex`, `regexp` | Instances of **RegExp** (regular expressions)
| `error`, `err` | Instances of **Error**
| `symbol` | Value is **Symbol** (using **typeof**)

@@ -454,2 +491,4 @@ | `empty` | Value is empty (e.g. **v.length === 0** (string/array), **v.size === 0** (Map/Set), `Object.keys(v) === 0` (objects), or `!v` (anything else)

### String modifiers - array type
Any string type can be made into an array of that type by appending `[]` brackets to the type reference. This means the check looks for a plain array whose contents only include the specified type.

@@ -465,7 +504,9 @@

// Fail.
check([1, 2], "str[]"); // Throws ValueError "Must be plain array containing: string (received [1, 2])"
check(["a"], "int[]"); // Throws ValueError "Must be plain array containing: integer (received ["a"])"
check([], "int[]+"); // Throws ValueError "Must be non-empty plain array containing: integer (received [])"
check([1, 2], "str[]"); // Throws ValueError "Must be plain array containing string (received [1, 2])"
check(["a"], "int[]"); // Throws ValueError "Must be plain array containing integer (received ["a"])"
check([], "int[]+"); // Throws ValueError "Must be non-empty plain array containing integer (received [])"
```
### String modifiers - tuple type
Array tuples can be specified by surrounding types in `[]` brackets.

@@ -480,30 +521,63 @@

// Fail.
check([true, true], "[str, str]") // Throws ValueError "Must be plain array tuple containing: string, string (received [true, true])"
check([true], "[bool, bool]") // Throws ValueError "Must be plain array tuple containing: boolean, boolean (received [true])"
check(["a", "b", "c"], "[str, str]") // Throws ValueError "Must be plain array tuple containing: string, string (received ["a", "b", "c"])"
check([true, true], "[str, str]") // Throws ValueError "Must be plain array tuple like [string, string] (received [true, true])"
check([true], "[bool, bool]") // Throws ValueError "Must be plain array tuple like [boolean, boolean] (received [true])"
check(["a", "b", "c"], "[str, str]") // Throws ValueError "Must be plain array tuple like [string, string] (received ["a", "b", "c"])"
```
Check for objects only containing strings of a specified type by surrounding the type in `{}` braces. This means the check looks for a plain object whose contents only include the specified type (whitespace is optional).
### String modifiers - object type
Check for objects only containing strings of a specified type by surrounding the type in `{}` braces. This means the check looks for a plain object whose contents only include the specified type (whitespace is optional). If you specify multiple props (separated by commas) they are treated like `OR` conditions.
```js
// Pass.
check({ a: "a", b: "b" }, "{str}"); // No error.
check({ a: 1, b: 2 }, "{int}"); // No error.
check({ a: 1, b: 2 }, "{ int }"); // No error.
check({}, "{int}"); // No error (empty is fine).
check({ a: 1 }, "{int}+"); // No error (non-empty).
check({ a: 1, b: "B" }, "{ int, str }"); // No error (integers or strings are fine).
// Fail.
check({ a: 1, b: 2 }, "{str}"); // Throws ValueError "Must be plain object containing: string (received [1, 2])"
check({ a: "a" }, "{int}"); // Throws ValueError "Must be plain object containing: integer (received ["a"])"
check({}, "{int}+"); // Throws ValueError "Must be non-empty plain object containing: integer (received [])"
check({ a: 1, b: 2 }, "{str}"); // Throws ValueError "Must be plain object like { string: string } (received { a: 1, b: 2 })"
check({ a: "a" }, "{ int }"); // Throws ValueError "Must be plain object like { string: integer } (received { a: "a" })"
check({}, "{int}+"); // Throws ValueError "Must be non-empty plain object like { string: integer } (received {})"
```
A type for the keys can also be specified by using `{ key: value }` format.
A type for the keys can also be specified by using `{ key: value }` format. Again multiple props can be specified separated by commas.
```js
// Pass.
check({ myVar: 123 }, "{ camel: integer }");
check({ "my-var": 123 }, "{ kebab: integer }");
check({ myVar: 123 }, "{ camel: int }"); // No error (key is camelCase).
check({ "my-var": 123 }, "{ kebab: int }"); // No error (key is kebab-case).
check({ "YAS": 123 }, "{ upper: bool }"); // No error (key is UPPERCASE).
check({ a: 1, B: true }, "{ lower: int, upper: bool }"); // No error (a is lowercase and integer, B is UPPERCASE and boolean).
// Fail.
check({ "myVar": 123 }, "{ kebab: int }"); // Throws ValueError "Must be plain object like { kebab-case string: integer } (received { "myVar": 123 })"
check({ "nope": true }, "{ upper: bool }"); // Throws ValueError "Must be plain object like { UPPERCASE string: boolean } (received { "nope": true })"
```
Exact props can be specified by wrapping the key string in quotes (single or double).
```js
// Pass.
check({ name: "Dave" }, '{ "name": str }');
check({ name: "Dave", age: 48 }, '{ "name": str, "age": int }');
// Fail.
check({ name: 123 }, '{ "name": str }'); // Throws ValueError "Must be plain object like { "name": string } (received etc)"...
check({ name: "Dave", age: "123" }, '{ "name": str, "age": int }'); // Throws ValueError "Must be plain object like { "name": string, "age": integer } (received etc)"
```
Exact prop checkers and normal checkers can be mixed in the same string type. If an exact key is specified it will be favoured.
```js
// Pass.
check({ name: "Dave", a: 1, b: 2 }, '{ "name": str, lower: int }');
// Fail.
check({ name: "Dave", a: 1, b: false }, '{ "name": str, lower: int }'); // Throws ValueError "Must be plain object like { "name": string, lowercase string: integer } (received etc)"
```
### String modifiers - optional type
Any string type can be made optional by appending a `?` question mark to the type reference. This means the check will also accept `undefined` in addition to the specified type.

@@ -523,2 +597,4 @@

### String modifiers - non-empty type
Any type can be made non-empty by appending a `+` plus sign to the type reference. This means the check will only pass if the value is non-empty. Specifically this works as follows:

@@ -545,2 +621,4 @@

### String modifiers - size type
To specify a size for the type, you can prepend minimum/maximum with e.g. `{12}`, `{4,8}`, `{4,}` or `{,8}` (e.g. RegExp style quantifiers). This allows you to specify e.g. a string with 12 characters, an array with between 10 and 20 items, or an integer with a minimum value of 4.

@@ -562,2 +640,4 @@

### String modifiers - inverted type
Any string type can inverted by prepending a `!` exclamation mark to the type reference. This means the check will only pass if the _inverse_ of its type is true.

@@ -578,2 +658,4 @@

### String modifiers - OR and AND combined types and grouped types
You can use `&` and `|` to join string types together, to form AND and OR chains of allowed types. This allows you to compose together more complex types like `number | string` or `date | number | null` or `string && custom-checker`

@@ -610,3 +692,3 @@

`()` parentheses can be used to create a 'grouped type'. This is useful to specify an array that allows several types, to make an invert/optional type of several types, or to state an explicit precence order for `&` and `|`.
`()` parentheses can be used to create a 'grouped type' which is useful to specify an array that allows several types, to make an invert/optional type of several types, or to state an explicit precence order for `&` and `|`.

@@ -778,3 +860,3 @@ ```js

Similarly, to check the format of tuples, pass an array with two or more items as the type. _If two or more types are in an type array, it is considered a tuple type and will be rejected if it does not conform exactly to the tuple._
Similarly to check the format of tuples pass an array with two or more items as the type. _If two or more types are in an type array, it is considered a tuple type and will be rejected if it does not conform exactly to the tuple._

@@ -796,8 +878,14 @@ ```js

## Roadmap
## Roadmap and ideas
- [ ] Support `@decorator` syntax for class methods (PRs welcome)
- [ ] Support `@decorator` syntax for class methods
- [ ] Allow `args()` to accept a string type e.g. in the format `"str, num, bool"`
## Changelog
- 8.3.0
- Add an error string checker, e.g. `check(new TypeError(), "error")`
- When ValueError auto-prefixes the name of the calling function, it skips anonymous functions in the stack
- When ValueError auto-prefixes the name of the calling function, it doesn't if the prefix already includes a ': ' colon space.
- Add return string type modifier, e.g. `check(123, `return num`)` (changes error message to e.g. `Must return X`)
- 8.2.0

@@ -804,0 +892,0 @@ - Add string string type, e.g. `"abc"`

@@ -91,2 +91,4 @@ const checkers = require("../../lib/checkers/checkers");

expect(mockCheck(/[abc]+/g, "regex")).toBe(undefined);
expect(mockCheck(new Error("abc"), "err")).toBe(undefined);
expect(mockCheck(new TypeError("abc"), "error")).toBe(undefined);
expect(mockCheck(Symbol(), "symbol")).toBe(undefined);

@@ -189,2 +191,4 @@

expect(() => mockCheck("/[abc]+/g", "regex")).toThrow(TypeError);
expect(() => mockCheck("abc", "err")).toThrow(TypeError);
expect(() => mockCheck(false, "error")).toThrow(TypeError);
expect(() => mockCheck("symbol", "symbol")).toThrow(TypeError);

@@ -191,0 +195,0 @@

@@ -442,2 +442,16 @@ const BlorkError = require("../../lib/errors/BlorkError");

});
describe("Return types", () => {
test("Return types pass correctly", () => {
expect(check("a", "return string")).toBe(undefined);
expect(check(123, "return number")).toBe(undefined);
});
test("Return types fail correctly", () => {
expect(() => check(123, "return string")).toThrow(TypeError);
expect(() => check("a", "return number")).toThrow(TypeError);
});
test("Correct error message", () => {
expect(() => check(123, "return string")).toThrow(/Must return string/);
expect(() => check("a", "return number")).toThrow(/Must return finite number/);
});
});
});

@@ -5,61 +5,107 @@ const { ValueError, EMPTY } = require("../../lib/exports");

describe("ValueError()", () => {
test("Return correct error with default message", () => {
expect(new ValueError()).toHaveProperty("name", "ValueError");
expect(new ValueError()).toHaveProperty("message", "Object.test(): Invalid value");
expect(new ValueError()).toHaveProperty("prefix", "Object.test()");
expect(new ValueError()).toHaveProperty("reason", "Invalid value");
expect(new ValueError()).not.toHaveProperty("value");
describe("Default reason", () => {
test("Return correct error with default reason (named function)", () => {
function abc() {
const e = new ValueError();
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "abc(): Invalid value");
expect(e).toHaveProperty("prefix", "abc()");
expect(e).toHaveProperty("reason", "Invalid value");
expect(e).not.toHaveProperty("value");
}
abc();
});
test("Return correct error with default reason (named function)", () => {
(() => {
const e = new ValueError();
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "Invalid value");
expect(e).toHaveProperty("prefix", "");
expect(e).toHaveProperty("reason", "Invalid value");
expect(e).not.toHaveProperty("value");
})();
});
});
test("Return correct error with message only", () => {
expect(new ValueError("Message")).toHaveProperty("name", "ValueError");
expect(new ValueError("Message")).toHaveProperty("message", "Object.test(): Message");
expect(new ValueError("Message")).toHaveProperty("prefix", "Object.test()");
expect(new ValueError("Message")).toHaveProperty("reason", "Message");
expect(new ValueError("Message")).not.toHaveProperty("value");
function abc() {
return new ValueError("Message");
}
expect(abc()).toHaveProperty("name", "ValueError");
expect(abc()).toHaveProperty("message", "abc(): Message");
expect(abc()).toHaveProperty("prefix", "abc()");
expect(abc()).toHaveProperty("reason", "Message");
expect(abc()).not.toHaveProperty("value");
describe("Reason", () => {
test("Return correct error with reason only (named function)", () => {
function abc() {
const e = new ValueError("Reason");
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "abc(): Reason");
expect(e).toHaveProperty("prefix", "abc()");
expect(e).toHaveProperty("reason", "Reason");
expect(e).not.toHaveProperty("value");
}
abc();
});
test("Return correct error with reason only (named function)", () => {
(() => {
const e = new ValueError("Reason");
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "Reason");
expect(e).toHaveProperty("prefix", "");
expect(e).toHaveProperty("reason", "Reason");
expect(e).not.toHaveProperty("value");
})();
});
});
test("Return correct error with message and value", () => {
expect(new ValueError("Message", 123)).toHaveProperty("name", "ValueError");
expect(new ValueError("Message", 123)).toHaveProperty("message", "Object.test(): Message (received 123)");
expect(new ValueError("Message", 123)).toHaveProperty("prefix", "Object.test()");
expect(new ValueError("Message", 123)).toHaveProperty("reason", "Message");
expect(new ValueError("Message", 123)).toHaveProperty("value", 123);
function abc() {
return new ValueError("Message", 123);
}
expect(abc()).toHaveProperty("name", "ValueError");
expect(abc()).toHaveProperty("message", "abc(): Message (received 123)");
expect(abc()).toHaveProperty("prefix", "abc()");
expect(abc()).toHaveProperty("reason", "Message");
expect(abc()).toHaveProperty("value", 123);
describe("Value", () => {
test("Return correct error with reason and value (named function)", () => {
function abc() {
const e = new ValueError("Reason", 123);
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "abc(): Reason (received 123)");
expect(e).toHaveProperty("prefix", "abc()");
expect(e).toHaveProperty("reason", "Reason");
expect(e).toHaveProperty("value", 123);
}
abc();
});
test("Return correct error with reason and value (anonymous function)", () => {
(() => {
const e = new ValueError("Reason", 123);
expect(e).toHaveProperty("message", "Reason (received 123)");
expect(e).toHaveProperty("prefix", "");
expect(e).toHaveProperty("reason", "Reason");
expect(e).toHaveProperty("value", 123);
})();
});
});
test("Return correct error with message, value, and prefix", () => {
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("name", "ValueError");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty(
"message",
"Object.test(): Prefix: Message (received 123)"
);
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("prefix", "Object.test(): Prefix");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("reason", "Message");
expect(new ValueError("Message", 123, "Prefix")).toHaveProperty("value", 123);
function abc() {
return new ValueError("Message", 123, "Prefix");
}
expect(abc()).toHaveProperty("name", "ValueError");
expect(abc()).toHaveProperty("message", "abc(): Prefix: Message (received 123)");
expect(abc()).toHaveProperty("prefix", "abc(): Prefix");
expect(abc()).toHaveProperty("reason", "Message");
expect(abc()).toHaveProperty("value", 123);
describe("Prefix", () => {
test("Return correct error with reason, value, and prefix (named function)", () => {
function abc() {
const e = new ValueError("Reason", 123, "Prefix");
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "abc(): Prefix: Reason (received 123)");
expect(e).toHaveProperty("prefix", "abc(): Prefix");
expect(e).toHaveProperty("reason", "Reason");
expect(e).toHaveProperty("value", 123);
}
abc();
});
test("Return correct error with reason, value, and prefix (named function but with prefix including ': ' colon space)", () => {
function abc() {
const e = new ValueError("Reason", 123, "myFunc(): Prefix");
expect(e).toHaveProperty("name", "ValueError");
expect(e).toHaveProperty("message", "myFunc(): Prefix: Reason (received 123)");
expect(e).toHaveProperty("prefix", "myFunc(): Prefix");
expect(e).toHaveProperty("reason", "Reason");
expect(e).toHaveProperty("value", 123);
}
abc();
});
test("Return correct error with reason, value, and prefix (anonymous function)", () => {
(() => {
const e = new ValueError("Reason", 123, "Prefix");
expect(e).toHaveProperty("message", "Prefix: Reason (received 123)");
expect(e).toHaveProperty("prefix", "Prefix");
expect(e).toHaveProperty("reason", "Reason");
expect(e).toHaveProperty("value", 123);
})();
});
});
test("Does not show value in message if value is EMPTY", () => {
expect(new ValueError("Message", EMPTY).hasOwnProperty("value")).toBe(false);
expect(new ValueError("Message", EMPTY).message).not.toMatch(/received/);
expect(new ValueError("Reason", EMPTY).hasOwnProperty("value")).toBe(false);
expect(new ValueError("Reason", EMPTY).message).not.toMatch(/received/);
});
});

@@ -5,72 +5,127 @@ const cause = require("../../lib/helpers/cause");

describe("cause()", () => {
test("Correct frame is returned (Chrome, Node, IE, Edge)", () => {
// Full stack from a random Blork error.
const stack = [
"ValueError: Must be finite string (received 123)",
" at throwError (classes/Blorker.js:41:83)",
" at runChecker (classes/Blorker.js:21:77)",
" at Blorker._check (classes/Blorker.js:261:109)",
" at Blorker$check (classes/Blorker.js:118:31)",
" at MyClass.name (MyClass.js:8:4)",
" at myFunc (helpers/myFunc.js:129:432)"
];
describe("Chrome, Node, IE, Edge", () => {
test("Correct frame is returned", () => {
// Full stack from a random Blork error.
const stack = [
"ValueError: Must be finite string (received 123)",
" at throwError (classes/Blorker.js:41:83)",
" at runChecker (classes/Blorker.js:21:77)",
" at Blorker._check (classes/Blorker.js:261:109)",
" at Blorker$check (classes/Blorker.js:118:31)",
" at MyClass.name (MyClass.js:8:4)",
" at myFunc (helpers/myFunc.js:129:432)"
];
// Get the cause stack frame from the frames.
expect(cause(stack.join("\n"))).toEqual({
function: "MyClass.name()",
file: "MyClass.js",
line: 8,
column: 4,
original: " at MyClass.name (MyClass.js:8:4)",
stack: [
// Get the cause stack frame from the frames.
const c = cause(stack.join("\n"));
expect(c.function).toBe("MyClass.name()");
expect(c.file).toBe("MyClass.js");
expect(c.line).toBe(8);
expect(c.column).toBe(4);
expect(c.original).toBe(" at MyClass.name (MyClass.js:8:4)");
expect(c.stack).toBe(
[
"ValueError: Must be finite string (received 123)",
" at MyClass.name (MyClass.js:8:4)",
" at myFunc (helpers/myFunc.js:129:432)"
].join("\n")
);
});
test("Anonymous functions are skipped over", () => {
// Full stack from a random Blork error.
const stack = [
"ValueError: Must be finite string (received 123)",
" at throwError (classes/Blorker.js:41:83)",
" at runChecker (classes/Blorker.js:21:77)",
" at Blorker._check (classes/Blorker.js:261:109)",
" at Blorker$check (classes/Blorker.js:118:31)",
" at <anonymous>:1:3", // Anonymous.
" at <anonymous>:1", // Anonymous.
" at <anonymous>", // Anonymous.
" at MyClass.name (MyClass.js:8:4)",
" at myFunc (helpers/myFunc.js:129:432)"
].join("\n")
];
// Get the cause stack frame from the frames.
const c = cause(stack.join("\n"));
expect(c.function).toBe("MyClass.name()");
expect(c.file).toBe("MyClass.js");
expect(c.line).toBe(8);
expect(c.column).toBe(4);
expect(c.original).toBe(" at MyClass.name (MyClass.js:8:4)");
expect(c.stack).toBe(
[
"ValueError: Must be finite string (received 123)",
" at MyClass.name (MyClass.js:8:4)",
" at myFunc (helpers/myFunc.js:129:432)"
].join("\n")
);
});
});
test("Correct frame is returned (Firefox, Safari)", () => {
// Full stack from a random Blork error.
const stack = [
"throwError@classes/Blorker.js:41:83",
"runChecker@classes/Blorker.js:21:77",
"Blorker._check@classes/Blorker.js:261:109",
"Blorker$check@classes/Blorker.js:118:31",
"MyClass.name@MyClass.js:8:4",
"myFunc@helpers/myFunc.js:129:432"
];
test("First frame is returned if no Blorker call is in the stack", () => {
// Full stack from a random Blork error.
const stack = [
"Error",
" at Object.test (functions/cause.test.js:8:4)",
" at Object.asyncFn (node_modules/jest-jasmine2/build/jasmine_async.js:129:432)",
" at resolve (node_modules/jest-jasmine2/build/queue_runner.js:51:12)",
" at new Promise (<anonymous>)",
" at mapper (node_modules/jest-jasmine2/build/queue_runner.js:40:274)",
" at promise.then (node_modules/jest-jasmine2/build/queue_runner.js:83:39)",
" at <anonymous>",
" at process._tickCallback (internal/process/next_tick.js:182:7)"
];
// Get the cause stack frame from the frames.
expect(cause(stack.join("\n"))).toEqual({
function: "MyClass.name()",
file: "MyClass.js",
line: 8,
column: 4,
original: "MyClass.name@MyClass.js:8:4",
stack: ["MyClass.name@MyClass.js:8:4", "myFunc@helpers/myFunc.js:129:432"].join("\n")
// Get the cause stack frame from the frames.
const c = cause(stack.join("\n"));
expect(c.function).toBe("Object.test()");
expect(c.file).toBe("functions/cause.test.js");
expect(c.line).toBe(8);
expect(c.column).toBe(4);
expect(c.original).toBe(" at Object.test (functions/cause.test.js:8:4)");
expect(c.stack).toBe(stack.join("\n"));
});
});
test("First frame is returned if no Blorker call is in the stack", () => {
// Full stack from a random Blork error.
const stack = [
"Error",
" at Object.test (functions/cause.test.js:8:4)",
" at Object.asyncFn (node_modules/jest-jasmine2/build/jasmine_async.js:129:432)",
" at resolve (node_modules/jest-jasmine2/build/queue_runner.js:51:12)",
" at new Promise (<anonymous>)",
" at mapper (node_modules/jest-jasmine2/build/queue_runner.js:40:274)",
" at promise.then (node_modules/jest-jasmine2/build/queue_runner.js:83:39)",
" at <anonymous>",
" at process._tickCallback (internal/process/next_tick.js:182:7)"
];
describe("Firefox, Safari", () => {
test("Correct frame is returned", () => {
// Full stack from a random Blork error.
const stack = [
"throwError@classes/Blorker.js:41:83",
"runChecker@classes/Blorker.js:21:77",
"Blorker._check@classes/Blorker.js:261:109",
"Blorker$check@classes/Blorker.js:118:31",
"MyClass.name@MyClass.js:8:4",
"myFunc@helpers/myFunc.js:129:432"
];
// Get the cause stack frame from the frames.
expect(cause(stack.join("\n"))).toEqual({
function: "Object.test()",
file: "functions/cause.test.js",
line: 8,
column: 4,
original: " at Object.test (functions/cause.test.js:8:4)",
stack: stack.join("\n")
// Get the cause stack frame from the frames.
const c = cause(stack.join("\n"));
expect(c.function).toBe("MyClass.name()");
expect(c.file).toBe("MyClass.js");
expect(c.line).toBe(8);
expect(c.column).toBe(4);
expect(c.original).toBe("MyClass.name@MyClass.js:8:4");
expect(c.stack).toBe(["MyClass.name@MyClass.js:8:4", "myFunc@helpers/myFunc.js:129:432"].join("\n"));
});
test("Anonymous functions are skipped over", () => {
// Full stack from a random Blork error.
const stack = [
"throwError@classes/Blorker.js:41:83",
"runChecker@classes/Blorker.js:21:77",
"Blorker._check@classes/Blorker.js:261:109",
"Blorker$check@classes/Blorker.js:118:31",
"@file:///C:/example.html:16:13", // Anonymous.
"@debugger eval code:21:9", // Anonymous.
"MyClass.name@MyClass.js:8:4",
"myFunc@helpers/myFunc.js:129:432"
];
// Get the cause stack frame from the frames.
const c = cause(stack.join("\n"));
expect(c.function).toBe("MyClass.name()");
expect(c.file).toBe("MyClass.js");
expect(c.line).toBe(8);
expect(c.column).toBe(4);
expect(c.original).toBe("MyClass.name@MyClass.js:8:4");
expect(c.stack).toBe(["MyClass.name@MyClass.js:8:4", "myFunc@helpers/myFunc.js:129:432"].join("\n"));
});
});

@@ -77,0 +132,0 @@ test("Undefined is returned if stack is not valid", () => {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc