CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tcompare

A comprehensive comparison library, for use in test frameworks

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration

tcompare provides extensive configuration options for customizing comparison behavior, diff output, and object formatting. All options are type-safe and well-documented for easy customization.

Capabilities

CompareOptions Type

Options available to all comparison functions, combining formatting and comparison-specific settings.

/**
 * Options that can be used to set how diffs are formatted
 */
type CompareOptions = FormatOptions & Pick<SameOptions, 'diffContext'>;

FormatOptions Interface

Core formatting options available to all formatting and comparison operations.

/**
 * Options to control the formatting of objects
 */
interface FormatOptions {
  /** Sort object keys alphabetically for deterministic output */
  sort?: boolean;
  /** Formatting style - controls output format and syntax */
  style?: StyleType;
  /** Number of bytes to show per line when printing long Buffers (default: 32) */
  bufferChunkSize?: number;
  /** Include enumerable properties from prototype chain */
  includeEnumerable?: boolean;
  /** Include getter properties (warning: may trigger side effects) */
  includeGetters?: boolean;
  /** Represent and compare React elements as JSX strings (pretty style only, default: true) */
  reactString?: boolean;
}

type StyleType = 'pretty' | 'js' | 'tight';

Usage Examples:

import { same, format } from "tcompare";

// Basic formatting options
const options = {
  sort: true,           // Alphabetical key sorting
  style: "js" as const, // JavaScript syntax
  bufferChunkSize: 16   // Smaller buffer chunks
};

const result = same(obj1, obj2, options);
const formatted = format(obj1, options);

SameOptions Interface

Extended options for all comparison classes, including the expected pattern and diff configuration.

/**
 * Options for all comparison operations
 */
interface SameOptions extends FormatOptions {
  /** The pattern to test against (required for comparison classes) */
  expect: any;
  /** Parent comparison object for nested comparisons */
  parent?: Same;
  /** Key in parent object being compared */
  key?: any;
  /** Corresponding key in expected pattern */
  expectKey?: any;
  /** Number of lines of context to show around changes in diffs (default: 10) */
  diffContext?: number;
}

Usage Examples:

import { Same } from "tcompare";

// Comprehensive comparison options
const options = {
  expect: { name: "Alice", age: 25 },
  style: "pretty" as const,
  sort: true,
  diffContext: 5,        // Show 5 lines of context around changes
  reactString: false     // Disable JSX formatting
};

const comparison = new Same(testObject, options);
const diff = comparison.print();

React Element Options

Options for configuring React element formatting when reactString is enabled.

/**
 * Options for React element to JSX string conversion
 * Re-exported from react-element-to-jsx-string package
 */
interface ReactElementToJSXStringOptions {
  /** Show default props in JSX output */
  showDefaultProps?: boolean;
  /** Show functions as anonymous functions */
  showFunctions?: boolean;
  /** Function to filter out props from JSX output */
  filterProps?: string[];
  /** Maximum depth for nested elements */
  maxInlineAttributesLineLength?: number;
  /** Sort props alphabetically */
  sortProps?: boolean;
  /** Use single quotes for props */
  useBooleanShorthandSyntax?: boolean;
  /** Tab size for indentation */
  tabStop?: number;
}

Usage Examples:

import { format } from "tcompare";
import type { ReactElementToJSXStringOptions } from "tcompare";

// React element formatting with custom options
const reactOptions: ReactElementToJSXStringOptions = {
  showDefaultProps: false,
  sortProps: true,
  useBooleanShorthandSyntax: true
};

const formatOptions = {
  style: "pretty" as const,
  reactString: true,
  // Note: ReactElementToJSXStringOptions are used internally
  // when reactString is true
};

const element = <MyComponent name="test" active={true} />;
const formatted = format(element, formatOptions);

Style Configuration

Three predefined styles with different output characteristics and use cases.

type StyleType = 'pretty' | 'js' | 'tight';

/**
 * Style configuration object defining how values are formatted
 */
interface Style {
  /** Format functions with optional class names */
  fn: (fn: Function | ((...a: any[]) => any), cls: string) => string;
  /** Format empty Set objects */
  setEmpty: (cls: string) => string;
  /** Format Set opening */
  setHead: (cls: string) => string;
  /** Format Set closing */
  setTail: (indent: string) => string;
  /** Separator between Set entries */
  setEntrySep: () => string;
  /** Format empty Map objects */
  mapEmpty: (cls: string) => string;
  /** Format Map opening */
  mapHead: (cls: string) => string;
  /** Format Map closing */
  mapTail: (indent: string) => string;
  /** Format Map key start */
  mapKeyStart: () => string;
  /** Separator between Map key and value */
  mapKeyValSep: () => string;
  /** Separator between Map entries */
  mapEntrySep: () => string;
  /** Format circular references */
  circular: (node: Format) => string;
  /** Format reference IDs */
  nodeId: (id: number) => string;
  /** Additional formatting methods for errors, objects, arrays, etc. */
  // ... extensive additional methods
}

/**
 * Predefined styles for different formatting needs
 */
const styles: { [style in StyleType]: Style };

Style Comparison Examples:

import { format, styles } from "tcompare";

const data = {
  map: new Map([["key1", "value1"], ["key2", "value2"]]),
  set: new Set(["a", "b", "c"]),
  array: [1, 2, 3]
};

// Pretty style - human readable with type indicators
console.log(format(data, { style: "pretty" }));
/*
Object {
  "map": Map {
    "key1" => "value1",
    "key2" => "value2",
  },
  "set": Set {
    "a",
    "b",
    "c",
  },
  "array": Array [
    1,
    2,
    3,
  ],
}
*/

// JavaScript style - valid JS syntax
console.log(format(data, { style: "js" }));
/*
{
  "map": new Map([
    ["key1", "value1"],
    ["key2", "value2"],
  ]),
  "set": new Set([
    "a",
    "b", 
    "c",
  ]),
  "array": [
    1,
    2,
    3,
  ],
}
*/

// Tight style - minimal whitespace
console.log(format(data, { style: "tight" }));
// {"map":new Map([["key1","value1"],["key2","value2"],]),"set":new Set(["a","b","c",]),"array":[1,2,3,],}

Diff Context Configuration

Control how much context is shown around changes in diff output.

interface SameOptions {
  /** 
   * Number of lines of context to show around changes in diffs
   * Higher values show more surrounding unchanged content
   * Lower values focus on just the changes
   * Default: 10
   */
  diffContext?: number;
}

Usage Examples:

import { same } from "tcompare";

const obj1 = {
  a: 1, b: 2, c: 3, d: 4, e: 5,
  f: 6, g: 7, h: 8, i: 9, j: 10,
  k: 11, l: 12, m: 13, n: 14, o: 15
};

const obj2 = {
  ...obj1,
  h: 999  // Changed value
};

// Minimal context - focus on changes
const minimalResult = same(obj1, obj2, { diffContext: 1 });
console.log(minimalResult.diff);
/*
--- expected
+++ actual
@@ -6,3 +6,3 @@
   "g": 7,
-  "h": 8,
+  "h": 999,
   "i": 9,
*/

// More context - show surrounding unchanged content
const contextResult = same(obj1, obj2, { diffContext: 5 });
console.log(contextResult.diff);
/*
--- expected  
+++ actual
@@ -4,7 +4,7 @@
   "e": 5,
   "f": 6,
   "g": 7,
-  "h": 8,
+  "h": 999,
   "i": 9,
   "j": 10,
   "k": 11,
*/

Buffer Configuration

Special configuration for Buffer object display.

interface FormatOptions {
  /**
   * Number of bytes to show per line when printing long Buffer objects
   * Each line shows hex values and ASCII representation
   * Default: 32 bytes per line
   */
  bufferChunkSize?: number;
}

Usage Examples:

import { format } from "tcompare";

const buffer = Buffer.from("Hello, World! This is a test buffer with more content.");

// Default chunk size (32 bytes per line)
console.log(format(buffer));
/*
Buffer <
  48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 20 54 68 |Hello, World! Th|
  69 73 20 69 73 20 61 20 74 65 73 74 20 62 75 66 |is a test buf|
  66 65 72 20 77 69 74 68 20 6d 6f 72 65 20 63 6f |fer with more co|
  6e 74 65 6e 74 2e                               |ntent.|
>
*/

// Smaller chunks (16 bytes per line)
console.log(format(buffer, { bufferChunkSize: 16 }));
/*
Buffer <
  48 65 6c 6c 6f 2c 20 57 |Hello, W|
  6f 72 6c 64 21 20 54 68 |orld! Th|
  69 73 20 69 73 20 61 20 |is a |
  74 65 73 74 20 62 75 66 |test buf|
  // ... continues
>
*/

// Larger chunks (64 bytes per line)
console.log(format(buffer, { bufferChunkSize: 64 }));
/*
Buffer <
  48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 20 54 68 69 73 20 69 73 20 61 20 74 65 73 74 20 62 |Hello, World! This is a test b|
  75 66 66 65 72 20 77 69 74 68 20 6d 6f 72 65 20 63 6f 6e 74 65 6e 74 2e                   |uffer with more content.|
>
*/

React Element Configuration

Control how React elements are formatted and compared.

interface FormatOptions {
  /**
   * Represent and compare React elements as JSX strings
   * Only supported in 'pretty' formatting style
   * When enabled, React elements are first compared as JSX strings
   * If JSX strings match, elements are considered equivalent
   * If JSX strings don't match, falls back to object comparison
   * Default: true
   */
  reactString?: boolean;
}

Usage Examples:

import { format, same } from "tcompare";
import React from "react";

const element1 = <div className="container">Hello</div>;
const element2 = <div className="container">Hello</div>;

// With JSX string formatting (default)
console.log(format(element1));
// <div className="container">Hello</div>

const result1 = same(element1, element2, { reactString: true });
console.log(result1.match); // true - JSX strings match

// Without JSX string formatting - shows object structure
console.log(format(element1, { reactString: false }));
/*
Object {
  "type": "div",
  "props": Object {
    "className": "container", 
    "children": "Hello",
  },
}
*/

Property Inclusion Configuration

Control which object properties are included in formatting and comparison.

interface FormatOptions {
  /**
   * Include enumerable properties from prototype chain
   * By default, only own properties are included
   * Warning: May include unexpected inherited properties
   */
  includeEnumerable?: boolean;
  
  /**
   * Include getter properties when formatting/comparing
   * Warning: Calling getters may trigger side effects
   */
  includeGetters?: boolean;
}

Usage Examples:

import { format } from "tcompare";

class Parent {
  parentProp = "parent";
  get parentGetter() { return "parent getter"; }
}

class Child extends Parent {
  childProp = "child";
  get childGetter() { return "child getter"; }
}

const instance = new Child();

// Default - only own properties
console.log(format(instance));
/*
Child {
  "childProp": "child",
}
*/

// Include enumerable properties from prototype
console.log(format(instance, { includeEnumerable: true }));
/*
Child {
  "childProp": "child",
  "parentProp": "parent",
}
*/

// Include getters (may trigger side effects)
console.log(format(instance, { includeGetters: true }));
/*
Child {
  "childProp": "child",
  "childGetter": "child getter",
}
*/

// Include both
console.log(format(instance, { 
  includeEnumerable: true, 
  includeGetters: true 
}));
/*
Child {
  "childProp": "child",
  "childGetter": "child getter",
  "parentProp": "parent",
  "parentGetter": "parent getter",
}
*/

Key Sorting Configuration

Enable deterministic output by sorting object keys alphabetically.

interface FormatOptions {
  /**
   * Sort object keys alphabetically
   * Ensures consistent output order regardless of key insertion order
   * Important for deterministic serialization and testing
   */
  sort?: boolean;
}

Usage Examples:

import { format } from "tcompare";

const obj = { z: 1, a: 2, m: 3, b: 4 };

// Default - insertion order preserved
console.log(format(obj));
/*
Object {
  "z": 1,
  "a": 2,
  "m": 3,
  "b": 4,
}
*/

// Sorted - alphabetical order
console.log(format(obj, { sort: true }));
/*
Object {
  "a": 2,
  "b": 4,
  "m": 3,
  "z": 1,
}
*/

Configuration Best Practices

Performance Considerations

  • Use includeGetters: false (default) to avoid side effects
  • Consider diffContext size for large objects - smaller values improve readability
  • tight style is fastest but least readable

Testing and Debugging

  • Use sort: true for deterministic test output
  • Increase diffContext when debugging complex object differences
  • Use pretty style for human-readable debugging output
  • Use js style when you need to copy-paste test data

Production Usage

  • Disable includeEnumerable unless specifically needed
  • Be cautious with includeGetters in production due to side effects
  • Consider bufferChunkSize based on your typical buffer sizes
  • Use appropriate style based on your output destination (logs, files, etc.)

Predefined Styles

The styles constant provides access to the three predefined formatting styles.

/**
 * Collection of predefined formatting styles
 */
const styles: { [style in StyleType]: Style };

/**
 * Individual style implementations
 */
interface Style {
  /** Format functions with optional class names */
  fn: (fn: Function, cls: string) => string;
  /** Format empty Set objects */
  setEmpty: (cls: string) => string;
  /** Format Set opening delimiter */
  setHead: (cls: string) => string;
  /** Format Set closing delimiter */
  setTail: (indent: string) => string;
  /** Format Map empty objects */
  mapEmpty: (cls: string) => string;
  /** Format Map opening delimiter */
  mapHead: (cls: string) => string;
  /** Format Map closing delimiter */
  mapTail: (indent: string) => string;
  /** Format circular reference markers */
  circular: (node: any) => string;
  /** Format node identifiers for circular references */
  nodeId: (id: number) => string;
  /** Additional formatting functions for Error objects, Buffers, Arrays, etc. */
  [key: string]: any;
}

Usage Examples:

import { styles, format } from "tcompare";

// Access individual style configurations
const prettyStyle = styles.pretty;
const jsStyle = styles.js;
const tightStyle = styles.tight;

// Custom formatting using specific style
const obj = { name: "test", values: [1, 2, 3] };

// These are equivalent:
console.log(format(obj, { style: "pretty" }));
console.log(new Format(obj, { style: "pretty" }).print());

// Direct style access for custom implementations
const customFormatter = {
  ...styles.pretty,
  // Override specific formatting functions
  fn: (fn: Function, cls: string) => `[Function: ${fn.name}]`
};

Install with Tessl CLI

npx tessl i tessl/npm-tcompare

docs

comparison-classes.md

comparison-functions.md

configuration.md

formatting.md

index.md

tile.json