 aacb45156b
			
		
	
	aacb45156b
	
	
	
		
			
			- Install Jest for unit testing with React Testing Library - Install Playwright for end-to-end testing - Configure Jest with proper TypeScript support and module mapping - Create test setup files and utilities for both unit and e2e tests Components: * Jest configuration with coverage thresholds * Playwright configuration with browser automation * Unit tests for LoginForm, AuthContext, and useSocketIO hook * E2E tests for authentication, dashboard, and agents workflows * GitHub Actions workflow for automated testing * Mock data and API utilities for consistent testing * Test documentation with best practices Testing features: - Unit tests with 70% coverage threshold - E2E tests with API mocking and user journey testing - CI/CD integration for automated test runs - Cross-browser testing support with Playwright - Authentication system testing end-to-end 🚀 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
pretty-format
Stringify any JavaScript value.
- Serialize built-in JavaScript types.
- Serialize application-specific data types with built-in or user-defined plugins.
Installation
$ yarn add pretty-format
Usage
const {format: prettyFormat} = require('pretty-format'); // CommonJS
import {format as prettyFormat} from 'pretty-format'; // ES2015 modules
const val = {object: {}};
val.circularReference = val;
val[Symbol('foo')] = 'foo';
val.map = new Map([['prop', 'value']]);
val.array = [-0, Infinity, NaN];
console.log(prettyFormat(val));
/*
Object {
  "array": Array [
    -0,
    Infinity,
    NaN,
  ],
  "circularReference": [Circular],
  "map": Map {
    "prop" => "value",
  },
  "object": Object {},
  Symbol(foo): "foo",
}
*/
Usage with options
function onClick() {}
console.log(prettyFormat(onClick));
/*
[Function onClick]
*/
const options = {
  printFunctionName: false,
};
console.log(prettyFormat(onClick, options));
/*
[Function]
*/
| key | type | default | description | 
|---|---|---|---|
| callToJSON | boolean | true | call toJSONmethod (if it exists) on objects | 
| compareKeys | function | undefined | compare function used when sorting object keys | 
| escapeRegex | boolean | false | escape special characters in regular expressions | 
| escapeString | boolean | true | escape special characters in strings | 
| highlight | boolean | false | highlight syntax with colors in terminal (some plugins) | 
| indent | number | 2 | spaces in each level of indentation | 
| maxDepth | number | Infinity | levels to print in arrays, objects, elements, and so on | 
| min | boolean | false | minimize added space: no indentation nor line breaks | 
| plugins | array | [] | plugins to serialize application-specific data types | 
| printBasicPrototype | boolean | false | print the prototype for plain objects and arrays | 
| printFunctionName | boolean | true | include or omit the name of a function | 
| theme | object | colors to highlight syntax in terminal | 
Property values of theme are from ansi-styles colors
const DEFAULT_THEME = {
  comment: 'gray',
  content: 'reset',
  prop: 'yellow',
  tag: 'cyan',
  value: 'green',
};
Usage with plugins
The pretty-format package provides some built-in plugins, including:
- ReactElementfor elements from- react
- ReactTestComponentfor test objects from- react-test-renderer
// CommonJS
const React = require('react');
const renderer = require('react-test-renderer');
const {format: prettyFormat, plugins} = require('pretty-format');
const {ReactElement, ReactTestComponent} = plugins;
// ES2015 modules and destructuring assignment
import React from 'react';
import renderer from 'react-test-renderer';
import {plugins, format as prettyFormat} from 'pretty-format';
const {ReactElement, ReactTestComponent} = plugins;
const onClick = () => {};
const element = React.createElement('button', {onClick}, 'Hello World');
const formatted1 = prettyFormat(element, {
  plugins: [ReactElement],
  printFunctionName: false,
});
const formatted2 = prettyFormat(renderer.create(element).toJSON(), {
  plugins: [ReactTestComponent],
  printFunctionName: false,
});
/*
<button
  onClick=[Function]
>
  Hello World
</button>
*/
Usage in Jest
For snapshot tests, Jest uses pretty-format with options that include some of its built-in plugins. For this purpose, plugins are also known as snapshot serializers.
To serialize application-specific data types, you can add modules to devDependencies of a project, and then:
In an individual test file, you can add a module as follows. It precedes any modules from Jest configuration.
import serializer from 'my-serializer-module';
expect.addSnapshotSerializer(serializer);
// tests which have `expect(value).toMatchSnapshot()` assertions
For all test files, you can specify modules in Jest configuration. They precede built-in plugins for React, HTML, and Immutable.js data types. For example, in a package.json file:
{
  "jest": {
    "snapshotSerializers": ["my-serializer-module"]
  }
}
Writing plugins
A plugin is a JavaScript object.
If options has a plugins array: for the first plugin whose test(val) method returns a truthy value, then prettyFormat(val, options) returns the result from either:
- serialize(val, …)method of the improved interface (available in version 21 or later)
- print(val, …)method of the original interface (if plugin does not have- serializemethod)
test
Write test so it can receive val argument of any type. To serialize objects which have certain properties, then a guarded expression like val != null && … or more concise val && … prevents the following errors:
- TypeError: Cannot read property 'whatever' of null
- TypeError: Cannot read property 'whatever' of undefined
For example, test method of built-in ReactElement plugin:
const elementSymbol = Symbol.for('react.element');
const test = val => val && val.$$typeof === elementSymbol;
Pay attention to efficiency in test because pretty-format calls it often.
serialize
The improved interface is available in version 21 or later.
Write serialize to return a string, given the arguments:
- valwhich “passed the test”
- unchanging configobject: derived fromoptions
- current indentationstring: concatenate toindentfromconfig
- current depthnumber: compare tomaxDepthfromconfig
- current refsarray: find circular references in objects
- printercallback function: serialize children
config
| key | type | description | 
|---|---|---|
| callToJSON | boolean | call toJSONmethod (if it exists) on objects | 
| compareKeys | function | compare function used when sorting object keys | 
| colors | Object | escape codes for colors to highlight syntax | 
| escapeRegex | boolean | escape special characters in regular expressions | 
| escapeString | boolean | escape special characters in strings | 
| indent | string | spaces in each level of indentation | 
| maxDepth | number | levels to print in arrays, objects, elements, and so on | 
| min | boolean | minimize added space: no indentation nor line breaks | 
| plugins | array | plugins to serialize application-specific data types | 
| printFunctionName | boolean | include or omit the name of a function | 
| spacingInner | strong | spacing to separate items in a list | 
| spacingOuter | strong | spacing to enclose a list of items | 
Each property of colors in config corresponds to a property of theme in options:
- the key is the same (for example, tag)
- the value in colorsis a object withopenandcloseproperties whose values are escape codes from ansi-styles for the color value intheme(for example,'cyan')
Some properties in config are derived from min in options:
- spacingInnerand- spacingOuterare newline if- minis- false
- spacingInneris space and- spacingOuteris empty string if- minis- true
Example of serialize and test
This plugin is a pattern you can apply to serialize composite data types. Side note: pretty-format does not need a plugin to serialize arrays.
// We reused more code when we factored out a function for child items
// that is independent of depth, name, and enclosing punctuation (see below).
const SEPARATOR = ',';
function serializeItems(items, config, indentation, depth, refs, printer) {
  if (items.length === 0) {
    return '';
  }
  const indentationItems = indentation + config.indent;
  return (
    config.spacingOuter +
    items
      .map(
        item =>
          indentationItems +
          printer(item, config, indentationItems, depth, refs), // callback
      )
      .join(SEPARATOR + config.spacingInner) +
    (config.min ? '' : SEPARATOR) + // following the last item
    config.spacingOuter +
    indentation
  );
}
const plugin = {
  test(val) {
    return Array.isArray(val);
  },
  serialize(array, config, indentation, depth, refs, printer) {
    const name = array.constructor.name;
    return ++depth > config.maxDepth
      ? '[' + name + ']'
      : (config.min ? '' : name + ' ') +
          '[' +
          serializeItems(array, config, indentation, depth, refs, printer) +
          ']';
  },
};
const val = {
  filter: 'completed',
  items: [
    {
      text: 'Write test',
      completed: true,
    },
    {
      text: 'Write serialize',
      completed: true,
    },
  ],
};
console.log(
  prettyFormat(val, {
    plugins: [plugin],
  }),
);
/*
Object {
  "filter": "completed",
  "items": Array [
    Object {
      "completed": true,
      "text": "Write test",
    },
    Object {
      "completed": true,
      "text": "Write serialize",
    },
  ],
}
*/
console.log(
  prettyFormat(val, {
    indent: 4,
    plugins: [plugin],
  }),
);
/*
Object {
    "filter": "completed",
    "items": Array [
        Object {
            "completed": true,
            "text": "Write test",
        },
        Object {
            "completed": true,
            "text": "Write serialize",
        },
    ],
}
*/
console.log(
  prettyFormat(val, {
    maxDepth: 1,
    plugins: [plugin],
  }),
);
/*
Object {
  "filter": "completed",
  "items": [Array],
}
*/
console.log(
  prettyFormat(val, {
    min: true,
    plugins: [plugin],
  }),
);
/*
{"filter": "completed", "items": [{"completed": true, "text": "Write test"}, {"completed": true, "text": "Write serialize"}]}
*/
The original interface is adequate for plugins:
- that do not depend on options other than highlightormin
- that do not depend on depthorrefsin recursive traversal, and
- if values either
- do not require indentation, or
- do not occur as children of JavaScript data structures (for example, array)
 
Write print to return a string, given the arguments:
- valwhich “passed the test”
- current printer(valChild)callback function: serialize children
- current indenter(lines)callback function: indent lines at the next level
- unchanging configobject: derived fromoptions
- unchanging colorsobject: derived fromoptions
The 3 properties of config are min in options and:
- spacingand- edgeSpacingare newline if- minis- false
- spacingis space and- edgeSpacingis empty string if- minis- true
Each property of colors corresponds to a property of theme in options:
- the key is the same (for example, tag)
- the value in colorsis a object withopenandcloseproperties whose values are escape codes from ansi-styles for the color value intheme(for example,'cyan')
Example of print and test
This plugin prints functions with the number of named arguments excluding rest argument.
const plugin = {
  print(val) {
    return `[Function ${val.name || 'anonymous'} ${val.length}]`;
  },
  test(val) {
    return typeof val === 'function';
  },
};
const val = {
  onClick(event) {},
  render() {},
};
prettyFormat(val, {
  plugins: [plugin],
});
/*
Object {
  "onClick": [Function onClick 1],
  "render": [Function render 0],
}
*/
prettyFormat(val);
/*
Object {
  "onClick": [Function onClick],
  "render": [Function render],
}
*/
This plugin ignores the printFunctionName option. That limitation of the original print interface is a reason to use the improved serialize interface, described above.
prettyFormat(val, {
  plugins: [pluginOld],
  printFunctionName: false,
});
/*
Object {
  "onClick": [Function onClick 1],
  "render": [Function render 0],
}
*/
prettyFormat(val, {
  printFunctionName: false,
});
/*
Object {
  "onClick": [Function],
  "render": [Function],
}
*/