CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tcompare

A comprehensive comparison library, for use in test frameworks

Pending
Overview
Eval results
Files

comparison-classes.mddocs/

Comparison Classes

tcompare provides direct access to comparison classes for advanced usage scenarios. These classes offer performance benefits when making multiple comparisons and allow for custom comparison logic through inheritance.

Class Hierarchy

Format
└── Same
    ├── Strict
    ├── Has
    │   ├── HasStrict (uses Strict.prototype.test)
    │   └── Match
    │       └── MatchStrict (fails if a==b && a!==b)
    ├── MatchOnly (uses Match.prototype.test)
    └── MatchOnlyStrict (uses MatchStrict.prototype.test)

Capabilities

Base Format Class

The foundational class for all formatting and comparison operations.

/**
 * Base formatting class for converting values to strings
 */
class Format {
  constructor(obj: any, options?: FormatOptions);
  
  /** Generate formatted string representation of the object */
  print(): string;
  
  /** Check if the object is an array-like structure */
  isArray(): boolean;
  
  /** Get object keys for plain objects */
  getPojoKeys(obj: any): string[];
  
  /** Get object entries for plain objects */
  getPojoEntries(obj: any): Array<[string, any]>;
}

Same Class

Base comparison class providing deep equivalence with loose matching.

/**
 * Base class for all comparison operations - deep equivalence with loose comparison
 */
class Same extends Format {
  constructor(obj: any, options: SameOptions);
  
  /** Boolean indicating whether objects match after calling print() */
  match: boolean;
  
  /** Perform the comparison test - returns boolean or 'COMPLEX' for nested comparison */
  test(): boolean | 'COMPLEX';
  
  /** Generate diff string and set match property */
  print(): string;
}

/**
 * Options for all comparison operations
 */
interface SameOptions extends FormatOptions {
  /** The pattern to test against */
  expect: any;
  /** Parent comparison object for nested comparisons */
  parent?: Same;
  /** Key in parent object */
  key?: any;
  /** Key in expected pattern */
  expectKey?: any;
  /** Number of lines of context to show in diffs */
  diffContext?: number;
}

Usage Examples:

import { Same } from "tcompare";

// Direct class usage
const comparison = new Same([1, 2, 3], { 
  expect: ["1", "2", "3"],
  style: "js" 
});

const diff = comparison.print();
console.log(comparison.match); // true
console.log(diff); // Empty string when match is true

Strict Class

Deep equality comparison without type coercion, extending Same.

/**
 * Deep equality comparison without type coercion
 */
class Strict extends Same {
  constructor(obj: any, options: SameOptions);
  
  /** Override test method to enforce strict equality */
  test(): boolean | 'COMPLEX';
}

Usage Examples:

import { Strict } from "tcompare";

const comparison = new Strict([1, 2, 3], { 
  expect: ["1", "2", "3"] 
});

console.log(comparison.print());
console.log(comparison.match); // false - no type coercion

Has Class

Subset matching - only tests properties present in the expected pattern.

/**
 * Subset matching - all pattern fields must exist in object with loose comparison
 */
class Has extends Same {
  constructor(obj: any, options: SameOptions);
  
  /** Override to only compare fields present in expected pattern */
  getPojoEntries(obj: any): Array<[string, any]>;
  
  /** Check if structure should be treated as array */  
  isArray(): boolean;
}

Usage Examples:

import { Has } from "tcompare";

const comparison = new Has(
  { name: "Alice", age: 25, city: "NYC" },
  { expect: { name: "Alice", age: "25" } }
);

console.log(comparison.match); // true - extra 'city' field ignored

HasStrict Class

Subset matching with strict comparison for primitives.

/**
 * Subset matching with strict comparison for primitives
 */
class HasStrict extends Has {
  constructor(obj: any, options: SameOptions);
  
  /** Use strict comparison for primitives, loose for objects */
  test(): boolean | 'COMPLEX';
}

Match Class

Most flexible matching strategy with pattern support.

/**
 * Flexible pattern matching with support for regex, constructors, and string patterns
 */
class Match extends Has {
  constructor(obj: any, options: SameOptions);
  
  /** Extended test method supporting multiple pattern types */
  test(): boolean | 'COMPLEX';
}

Usage Examples:

import { Match } from "tcompare";

// Pattern matching with regular expressions
const regexMatch = new Match("hello@example.com", {
  expect: /@example\.com$/
});

// Constructor pattern matching
const typeMatch = new Match(42, {
  expect: Number
});

// String substring matching
const stringMatch = new Match("hello world", {
  expect: "world"
});

MatchOnly Class

Pattern matching with strict object shape requirements.

/**
 * Uses Match test but requires exact object shape (no extra fields)
 */
class MatchOnly extends Same {
  constructor(obj: any, options: SameOptions);
  
  /** Use Match.prototype.test for comparison logic */
  test(): boolean | 'COMPLEX';
}

MatchStrict Class

Pattern matching without type coercion.

/**
 * Like Match but fails on loose equality without strict equality
 */
class MatchStrict extends Match {
  constructor(obj: any, options: SameOptions);
  
  /** Enhanced test that rejects loose-but-not-strict equality */
  test(): boolean | 'COMPLEX';
}

MatchOnlyStrict Class

Most restrictive matching - strict patterns with exact object shape.

/**
 * Uses MatchStrict test but requires exact object shape
 */
class MatchOnlyStrict extends Same {
  constructor(obj: any, options: SameOptions);
  
  /** Use MatchStrict.prototype.test for comparison logic */
  test(): boolean | 'COMPLEX';
}

Advanced Usage Patterns

Performance Optimization

When making many comparisons with the same options, instantiate classes directly to avoid function call overhead:

import { Same, SameOptions } from "tcompare";

const options: SameOptions = {
  expect: { name: String, age: Number },
  style: "js",
  diffContext: 5
};

// Reuse options object for multiple comparisons
const users = [
  { name: "Alice", age: 25 },
  { name: "Bob", age: 30 },
  { name: "Charlie", age: "invalid" } // Will fail
];

users.forEach(user => {
  const comparison = new Same(user, { ...options, expect: options.expect });
  const diff = comparison.print();
  
  if (!comparison.match) {
    console.log(`Invalid user: ${diff}`);
  }
});

Custom Comparison Logic

Extend existing classes to implement custom comparison behavior:

import { Match } from "tcompare";

class EmailMatch extends Match {
  test(): boolean | 'COMPLEX' {
    const obj = this.object;
    const pattern = this.expect;
    
    // Custom email validation logic
    if (typeof pattern === 'string' && pattern === 'email') {
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      return typeof obj === 'string' && emailRegex.test(obj);
    }
    
    // Fall back to parent logic
    return super.test();
  }
}

// Usage
const emailComparison = new EmailMatch("user@example.com", {
  expect: 'email'
});

console.log(emailComparison.match); // true for valid email

Accessing Internal State

Classes expose internal properties for advanced inspection:

import { Same } from "tcompare";

const comparison = new Same({ a: 1, b: 2 }, {
  expect: { a: 1, b: 3 }
});

// Access internal object and expected pattern
console.log('Testing:', comparison.object);
console.log('Against:', comparison.expect);

// Generate diff and check match
const diff = comparison.print();
console.log('Match:', comparison.match);
console.log('Diff:', diff);

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