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

tcompare

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tcompare - npm Package Compare versions

Comparing version 5.0.7 to 6.0.0

dist/cjs/format.d.ts

65

package.json
{
"name": "tcompare",
"version": "5.0.7",
"version": "6.0.0",
"description": "A comprehensive comparison library, for use in test frameworks",
"main": "index.js",
"repository": {

@@ -12,18 +11,55 @@ "type": "git",

"license": "ISC",
"main": "./dist/cjs/index.js",
"module": "./dist/mjs/index.js",
"exports": {
".": {
"import": "./dist/mjs/index.js",
"require": "./dist/cjs/index.js"
},
"./plugin-base": {
"import": "./dist/mjs/plugin-base.js",
"require": "./dist/cjs/plugin-base.js"
}
},
"files": [
"index.js",
"lib/*.js"
"dist"
],
"dependencies": {
"diff": "^4.0.2"
"diff": "^5.1.0"
},
"devDependencies": {
"tap": "^15.0.8"
"@types/diff": "^5.0.2",
"@types/node": "^18.11.9",
"@types/tap": "^15.0.7",
"c8": "^7.12.0",
"prettier": "^2.8.0",
"tap": "^16.3.2",
"ts-node": "^10.9.1",
"typedoc": "^0.23.21",
"typescript": "^4.9.3"
},
"prettier": {
"semi": false,
"printWidth": 60,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"scripts": {
"test": "tap",
"snap": "tap",
"snap": "c8 tap",
"test": "c8 tap",
"preprepare": "rm -rf dist",
"prepare": "tsc -p tsconfig-cjs.json && tsc -p tsconfig-esm.json",
"postprepare": "bash fixup.sh",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"format": "prettier --write . --loglevel warn",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
"prepublishOnly": "git push origin --follow-tags",
"typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts"
},

@@ -34,8 +70,13 @@ "tap": {

],
"check-coverage": true,
"coverage-map": "map.js"
"coverage": false,
"node-arg": [
"--no-warnings",
"--loader",
"ts-node/esm"
],
"ts": false
},
"engines": {
"node": ">=10"
"node": ">=16"
}
}

329

README.md
# tcompare
A comprehensive comparison library, for use in test frameworks. Walks an
object once, generating both a simple true/false result, as well as a
nicely formatted human-readable diff string.
A comprehensive comparison library, for use in test frameworks.
Walks an object once, generating both a simple true/false result,
as well as a string representation of both the actual and
expected values (highlighting just the parts that differ) and a
patch-style diff string.
## USAGE
```js
const { match, same, strict, has, hasStrict, format } = require('tcompare')
```ts
// require() is fine too
import {
match,
same,
strict,
has,
hasStrict,
matchOnly,
matchStrict,
} from 'tcompare'
import type { Result } from 'tcompare'
// Result is an object with { Boolean match, String diff }
const result = match(object, pattern)
const result: Result = match(object, pattern)
if (!result.match) {

@@ -20,111 +31,191 @@ console.log(`item did not match pattern`)

}
// raw classes exported also
import { MatchOnly } from 'tcompare'
const mo = new MatchOnly(
{ a: 1, b: 2 },
{ expect: { a: Number } }
)
const diff: string = mo.print()
console.log(mo.match) // false
console.log(diff)
/*
--- expected
+++ actual
@@ -1,2 +1,3 @@
Object {
+ "b": 2,
}
*/
```
## METHODS
- `indent` - String to indent each nested level. Defaults to `' '`.## METHODS
* `format(object, [options])` - No comparisons performed. Just print out the
object. Returns just the string format.
* `same(object, pattern, [options])` - Ensure that all items in the pattern are
found in the object, and vice versa, matching loosely (so, for example `1`
will match with `'1'`).
* `strict(object, pattern, [options])` - Ensure that all items in the pattern
are found in the object, and vice versa, matching strictly (so, for example
`1` will not match with `'1'`). Objects must have the same constructors,
and all fields will be matched recursively using the same `strict` test.
* `has(object, pattern, [options])` - Ensure that all items in the pattern are
found in the object, but ignore additional items found in the object,
matching loosely.
* `hasStrict(object, pattern, [options])` - Ensure that all items in the
pattern are found in the object, but ignore additional items found in the
object, matching strictly. Constructors do _not_ have to match between
objects, but if `constructor` is set as an ownProperty on the pattern
object, then it will be checked.
* `match(object, pattern, [options])` - Verify that all items in `pattern` are
found in `object`, and that they match. This is the loosest possible
algorithm, allowing cases where we just want to verify that an object
contains a few important properties. The algorithm is the same as
the one used by [tmatch](http://npm.im/tmatch). In a nutshell:
* If the object and pattern are loosely equal, then pass
* If the object and the pattern are both Regular Expressions, Date objects
or Buffers, then pass if they're "equivalent".
* If the pattern is a RegExp, cast object to a string, and test against the
RegExp.
* If both are Strings, pass if pattern appears in object.
* If pattern is a function, and object is an instance of that function,
then pass. (This also applies to Symbol, Number, String, etc.)
* If pattern and object are collections (object, map, set, array or
iterable), then compare their contents. Each type of collection can only
match its same type, with the exception of non-Set iterables (including
`arguments` objects), which are cast to Arrays.
Each method corresponds to an exported class. Except for
`format()` (which returns a string), they all return a `Result`
object. (That is, `{diff:string, match:boolean}`.)
There are classes exported to correspond to each of these. All of these are
instantiated like `new Format(object, options)`. An `expect` option is
required for all classes except `Format`. Call `obj.print()` on the resulting
object to generate a diff. Once the diff (or format) is generated, it'll have
- `format(object, [options])` - No comparisons performed. Just print out the
object. Returns just the formatted string.
- `same(object, pattern, [options])` - Deep equivalence. Ensure
that all items in the pattern are found in the object, and vice
versa, matching loosely (so, for example `1` will match with
`'1'`).
- `strict(object, pattern, [options])` - Deep equality. Ensure
that all items in the pattern are found in the object, and vice
versa, matching strictly (so, for example `1` will not match
with `'1'`). Objects must have the same constructors, and all
fields will be matched recursively using the same `strict`
test.
- `has(object, pattern, [options])` - Ensure that all items in
the pattern are found in the object, but ignore additional
items found in the object, matching loosely. Classes only need
to match loosely, so a plain JavaScript object can be used to
check for fields on a class instance.
- `hasStrict(object, pattern, [options])` - Ensure that all items
in the pattern are found in the object, but ignore additional
items found in the object, matching strictly. Constructors do
_not_ have to match between objects, but if `constructor` is
set as an ownProperty on the pattern object, then it will be
checked for strict equality.
- `match(object, pattern, [options])` - Verify that all items in
`pattern` are found in `object`, and that they match in an
extremely loose way. This is the loosest possible algorithm,
allowing cases where we just want to verify that an object
contains a few important properties. In summary:
- If the object and pattern are loosely equal, then pass
- If the object and the pattern are both Regular Expressions,
Date objects or Buffers, then pass if they represent
equivalent values.
- If the pattern is a RegExp, cast object to a string, and
test against the RegExp.
- If both are Strings, pass if pattern appears in object. (
- If pattern is a function, and object is an instance of that
function, then pass. (This also applies to Symbol, Number,
String, etc.)
- If pattern and object are collections (object, map, set,
array or iterable), then compare their contents. Each type
of collection can only match its same type, with the
exception of non-Set iterables (including `arguments`
objects), which are cast to Arrays.
- `matchOnly(object, pattern, [options])` - Same comparison
testing as `match()`, but will fail if the `object` has any
properties that are not present in the `pattern`.
- `matchStrict(object, pattern, [options])` - Same comparison
testing as `match()`, but will fail when two values are
equivalent but not strictly equal. (That is, when `a == b &&
!(a === b)`.)
There are classes exported to correspond to each of these. All of these are
instantiated like `new Format(object, options)`. An `expect` option is
required for all classes except `Format`. Call `obj.print()` on the resulting
object to generate a diff. Once the diff (or format) is generated, it'll have
a `match` boolean member.
## Classes
The exported classes should usually not be used directly, and
their implementation details are subject to change as needed
between versions.
The class heirarchy is:
```
Format
+-- Same
+-- Strict
+-- Has
| +-- HasStrict (uses Strict.prototype.test)
| +-- Match
| +-- MatchStrict (fails if a==b && a!==b)
+-- MatchOnly (uses Match.prototype.test)
```
In order to compare or print an object, instantiate one of the
classes, and call then the `print()` method, which will return
the diff or formatted value. The `match` boolean property will
be set after calling `print()`. If the objects match, then the
returned `diff` will also be an empty string.
## OPTIONS
Each method can take the following options.
### `FormatOptions` type
* `includeEnumerable` - Set to `true` to walk over _all_ enumerable
properties of a given object when comparing or formatting, rather than
the default of only showing enumerable own-properties. Note that
calling getter functions may be hazardous, as they may trigger
side-effects.
Every method and class can take the following options.
* `includeGetters` - Set to `true` to walk over all enumerable getters
on an object's prototype (but not from further down the prototype
chain), in addition to own-properties. This is useful in cases where
you want to compare or print an object with enumerable getters that
return internal values in a read-only manner. Note that calling
getter functions can be hazardous, as they may trigger side-effects.
* `sort` - Set to `true` to sort object keys. This is important when
- `sort` - Set to `true` to sort object keys. This is important when
serializing in a deterministic way.
* `style` - Set to `pretty` for a very human-readable style of object printing.
Set to `js` for a copy-and-paste friendly valid JavaScript output. Set to
`tight` for a minimal white-space js format. Default is `pretty`. Example:
- `style` - Set to `pretty` for a very human-readable style of object printing.
Set to `js` for a copy-and-paste friendly valid JavaScript output. Set to
`tight` for a minimal white-space js format. Default is `pretty`. Example:
```
// pretty style
Object {
"myMap": Map {
Object {
"a": 1,
} => Object {
"b": 2,
}
```
// pretty style
Object {
"myMap": Map {
Object {
"a": 1,
} => Object {
"b": 2,
}
}
}
// js style
{
"myMap": new Map([
[{
"a": 1,
}, {
"b": 2,
}]
])
}
// js style
{
"myMap": new Map([
[{
"a": 1,
}, {
"b": 2,
}]
])
}
// tight style
{"myMap":new Map([[{"a":1,},{"b":2,}],]),}
```
// tight style
{"myMap":new Map([[{"a":1,},{"b":2,}],]),}
```
Note that `tight` is not suitable for comparisons, only formatting.
Note that `tight` is not suitable for comparisons, only formatting.
- `bufferChunkSize` - The number of bytes to show per line when
printing long `Buffer` objects. Defaults to 32.
- `indent` - String to indent each nested level. Defaults to `' '`.
- `includeEnumerable` - Set to `true` to walk over _all_
enumerable properties of a given object when comparing or
formatting, rather than the default of only showing enumerable
own-properties. Note that calling getter functions may be
hazardous, as they may trigger side-effects.
- `includeGetters` - Set to `true` to walk over all enumerable
getters on an object's prototype (but not from further down the
prototype chain), in addition to own-properties. This is useful
in cases where you want to compare or print an object with
enumerable getters that return internal values in a read-only
manner. Note that calling getter functions can be hazardous, as
they may trigger side-effects.
### `SameOptions` type
Comparison classes also take the following options.
- `expect` - required. The pattern object to compare against.
- `diffContext` - Optional, default 10. Number of lines of
context to show in diff output.
## Circular References
Circular references are displayed using YAML-like references, so it's easy to
determine _which_ item is circularly referenced.
Circular references are displayed using YAML-like references, in
order to determine _which_ item is circularly referenced.
When doing comparisons, a pattern and object will be considered matching if
they contain the _same_ circularity. So, for example, if a pattern refers to
itself, then an object should refer to itself as well.
When doing comparisons, a pattern and object will be considered
matching if they contain the _same_ circularity. So, for example,
if a pattern refers to itself, then an object should refer to
itself as well.
```js
const a = {list: [], b: {}}
const a = { list: [], b: {} }
a.list.push(a)

@@ -150,3 +241,53 @@ a.list.push(a.b)

Note that circular references are never going to be valid JavaScript, even when
using the `js` style.
Note that circular references are never going to be valid
JavaScript, even when using the `js` style.
### Caveat: Circularity Between Pattern and Object Gets Weird
It's possible to get strange output when an object and pattern
refer to one another.
```js
import { same } from 'tcompare'
const a = {}
a.o = a
const b = { o: a }
console.error(same(a, b).diff)
// produces this confusing output:
/*
--- expected
+++ actual
@@ -1,5 +1,3 @@
&ref_1 Object {
- "o": &ref_1 Object {
- "o": <*ref_1>,
- },
+ "o": <*ref_1>,
}
*/
```
The more correct output would be something like:
```
--- expected
+++ actual
@@ -1,5 +1,3 @@
&ref_1 Object {
- "o": &ref_2 Object {
- "o": <*ref_2>,
- },
+ "o": <*ref_1>,
}
```
However, this requires tracking IDs in a much more complicated
way, being aware of whether the object is being read as an
pattern object or test object when determining its reference ID.
Since this is a relatively unusual thing to happen, and only
affects the output (but still properly detects whether it should
be treated as a match or not), it will likely not be addressed.
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