Skip to main content
Testers determine which renderer is most appropriate for rendering a given UI schema element. They return a numeric rank, with higher values indicating better matches.

Core Concepts

NOT_APPLICABLE

Constant indicating a tester cannot handle a schema/UI schema combination.
export const NOT_APPLICABLE = -1;

Tester

Function that tests if a renderer can handle a UI schema element.
type Tester = (
  uischema: UISchemaElement,
  schema: JsonSchema,
  context: TesterContext
) => boolean

RankedTester

Function that returns a numeric rank indicating renderer applicability.
type RankedTester = (
  uischema: UISchemaElement,
  schema: JsonSchema,
  context: TesterContext
) => number

TesterContext

Additional context passed to testers.
interface TesterContext {
  rootSchema: JsonSchema;  // Root schema for reference resolution
  config: any;              // Form-wide configuration
}

Creating Ranked Testers

rankWith

Create a ranked tester from a boolean tester and rank.
function rankWith(
  rank: number,
  tester: Tester
): RankedTester
rank
number
required
Numeric rank (higher = higher priority). Typically 1-10.
tester
Tester
required
Boolean tester function
return
RankedTester
Ranked tester that returns rank if tester passes, NOT_APPLICABLE otherwise
Example:
import { rankWith, isControl, schemaTypeIs, and } from '@jsonforms/core';

// Create a ranked tester for string controls
const stringControlTester = rankWith(
  3,
  and(isControl, schemaTypeIs('string'))
);

// Usage in renderer registration
import { MyStringControl } from './MyStringControl';

export default {
  tester: stringControlTester,
  renderer: MyStringControl
};

withIncreasedRank

Increase the rank of an existing ranked tester.
function withIncreasedRank(
  by: number,
  rankedTester: RankedTester
): RankedTester
by
number
required
Amount to increase rank by
rankedTester
RankedTester
required
Existing ranked tester
return
RankedTester
New ranked tester with increased rank
Example:
import { withIncreasedRank, stringControlTester } from '@jsonforms/core';

// Make string control higher priority
const highPriorityStringTester = withIncreasedRank(2, stringControlTester);

UI Schema Testers

isControl

Test if UI schema element is a control.
function isControl(uischema: any): uischema is ControlElement
uischema
any
required
UI schema element to test
return
boolean
True if uischema is a control (has a scope property)
Example:
import { isControl } from '@jsonforms/core';

if (isControl(uischema)) {
  console.log('Scope:', uischema.scope);
}

uiTypeIs

Test if UI schema has a specific type.
function uiTypeIs(expected: string): Tester
expected
string
required
Expected UI schema type (e.g., ‘Control’, ‘VerticalLayout’)
return
Tester
Tester function
Example:
import { uiTypeIs } from '@jsonforms/core';

const isControlTester = uiTypeIs('Control');
const isLayoutTester = uiTypeIs('VerticalLayout');

Schema Testers

schemaMatches

Test if resolved schema matches a predicate.
function schemaMatches(
  predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean
): Tester
predicate
(schema: JsonSchema, rootSchema: JsonSchema) => boolean
required
Function to test the resolved schema
return
Tester
Tester that resolves the control’s scope and applies the predicate
Example:
import { schemaMatches } from '@jsonforms/core';

const hasEnumTester = schemaMatches((schema) => {
  return schema.enum !== undefined;
});

schemaTypeIs

Test if schema has a specific type.
function schemaTypeIs(expectedType: string): Tester
expectedType
string
required
Expected schema type (‘string’, ‘number’, ‘integer’, ‘boolean’, ‘object’, ‘array’)
return
Tester
Tester function
Example:
import { schemaTypeIs } from '@jsonforms/core';

const isStringSchema = schemaTypeIs('string');
const isNumberSchema = schemaTypeIs('number');
const isArraySchema = schemaTypeIs('array');

formatIs

Test if schema has a specific format.
function formatIs(expectedFormat: string): Tester
expectedFormat
string
required
Expected schema format (e.g., ‘date’, ‘time’, ‘date-time’, ‘email’)
return
Tester
Tester for string schemas with the specified format
Example:
import { formatIs, rankWith, and, isControl } from '@jsonforms/core';

const dateControlTester = rankWith(
  3,
  and(isControl, formatIs('date'))
);

schemaSubPathMatches

Test a sub-path of the resolved schema.
function schemaSubPathMatches(
  subPath: string,
  predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean
): Tester
subPath
string
required
Path within the resolved schema (e.g., ‘items’, ‘properties.foo’)
predicate
(schema: JsonSchema, rootSchema: JsonSchema) => boolean
required
Predicate to apply to the sub-schema
return
Tester
Tester function

Scope Testers

scopeEndsWith

Test if control scope ends with a string.
function scopeEndsWith(expected: string): Tester
expected
string
required
Expected scope ending
return
Tester
Tester function
Example:
import { scopeEndsWith } from '@jsonforms/core';

const endsWithEmail = scopeEndsWith('email');
// Matches: '#/properties/email', '#/properties/user/properties/email'

scopeEndIs

Test if the last segment of the scope matches exactly.
function scopeEndIs(expected: string): Tester
expected
string
required
Expected last segment
return
Tester
Tester function
Example:
import { scopeEndIs } from '@jsonforms/core';

const isEmailField = scopeEndIs('email');
// Matches: '#/properties/email' but NOT '#/properties/primaryEmail'

Option Testers

optionIs

Test if UI schema has an option with a specific value.
function optionIs(optionName: string, optionValue: any): Tester
optionName
string
required
Option name to check
optionValue
any
required
Expected option value
return
Tester
Tester function
Example:
import { optionIs, and, isControl, rankWith } from '@jsonforms/core';

const multilineTester = rankWith(
  3,
  and(isControl, optionIs('multi', true))
);

hasOption

Test if UI schema has an option defined.
function hasOption(optionName: string): Tester
optionName
string
required
Option name to check for
return
Tester
Tester that returns true if option exists (regardless of value)

Composition Testers

and

Combine testers with logical AND.
function and(...testers: Tester[]): Tester
testers
Tester[]
required
Testers to combine
return
Tester
Tester that returns true only if all testers pass
Example:
import { and, isControl, schemaTypeIs, formatIs } from '@jsonforms/core';

const dateControlTester = and(
  isControl,
  schemaTypeIs('string'),
  formatIs('date')
);

or

Combine testers with logical OR.
function or(...testers: Tester[]): Tester
testers
Tester[]
required
Testers to combine
return
Tester
Tester that returns true if any tester passes
Example:
import { or, formatIs, optionIs } from '@jsonforms/core';

const dateFormatTester = or(
  formatIs('date'),
  optionIs('format', 'date')
);

not

Negate a tester.
function not(tester: Tester): Tester
tester
Tester
required
Tester to negate
return
Tester
Tester that returns opposite of input tester
Example:
import { not, schemaTypeIs } from '@jsonforms/core';

const notStringTester = not(schemaTypeIs('string'));

Predefined Testers

JSON Forms provides predefined testers for common scenarios:
// Basic type controls
export const isBooleanControl: Tester;
export const isIntegerControl: Tester;
export const isNumberControl: Tester;
export const isStringControl: Tester;
export const isObjectControl: Tester;

// Format controls
export const isDateControl: Tester;
export const isTimeControl: Tester;
export const isDateTimeControl: Tester;

// Enum controls
export const isEnumControl: Tester;
export const isOneOfEnumControl: Tester;

// Array controls
export const isObjectArrayControl: Tester;
export const isPrimitiveArrayControl: Tester;
export const isObjectArray: Tester;

// Combinator controls
export const isAllOfControl: Tester;
export const isAnyOfControl: Tester;
export const isOneOfControl: Tester;

// Special controls
export const isMultiLineControl: Tester;
export const isRangeControl: Tester;
export const isNumberFormatControl: Tester;
Example Usage:
import { rankWith, isStringControl } from '@jsonforms/core';

export const MyStringControlTester = rankWith(3, isStringControl);

Tester Best Practices

Rank Guidelines

  • 1-2: Generic/fallback renderers
  • 3-5: Standard renderers for basic types
  • 6-8: Specialized renderers (format-specific, options)
  • 9-10: Very specific renderers (custom business logic)

Example Ranking Strategy

import { rankWith, and, isControl, schemaTypeIs, formatIs } from '@jsonforms/core';

// Generic text input (rank 3)
const textTester = rankWith(3, and(isControl, schemaTypeIs('string')));

// Email input (rank 5)
const emailTester = rankWith(5, and(isControl, formatIs('email')));

// Custom business email (rank 8)
const businessEmailTester = rankWith(
  8,
  and(isControl, formatIs('email'), scopeEndsWith('businessEmail'))
);

Efficient Testers

import { and, isControl, schemaTypeIs } from '@jsonforms/core';

// Good: Fast checks first
const efficientTester = and(
  isControl,              // Fast UI schema check
  schemaTypeIs('string'), // Schema resolution
  customCheck             // Expensive custom logic
);

// Less efficient: Expensive checks first
const inefficientTester = and(
  customExpensiveCheck,   // Slow
  schemaTypeIs('string'), // Medium
  isControl               // Fast
);

Build docs developers (and LLMs) love