Vitest is being used and reference Vitest globals such as describe() and expect().
Basic usage
The primary entry point is thecreateRenderer() function. This function requires an extension point location (e.g., 'crm.record.tab'), and returns a renderer object with a render() method and utilities for querying and interacting with the rendered output. Mocks for supported React hooks and the Extension Point API are automatically provided based on the specified extension point location.
The extension point location (e.g.,
'crm.record.tab') is required because it determines the shape of the context, actions, and runServerlessFunction mocks that are automatically provided to your components during testing. Valid extension point locations include:'crm.record.tab''crm.record.sidebar''crm.preview''helpdesk.sidebar''settings''home'
Querying components
findByTestId
findByTestId(component, testId)
Finds a component by its testId prop. This is the recommended way to precisely find rendered components. This method throws an error if no match is found.
The non-throwing variant is maybeFindByTestId().
It’s recommended to use test IDs because they provide a stable, explicit way to identify components in your tests. Unlike matchers based on props or text content, test IDs won’t break when you change the component’s appearance or behavior. This makes your tests more maintainable and less brittle.
find
find(component, matcher?)
Finds the first descendant element that matches the given component and an optional matcher. Throws an error if no match is found.
The non-throwing variant is maybeFind().
findAll
findAll(component, matcher?)
Finds all descendant elements that match the given component and an optional matcher. Returns an array of all matching elements, or an empty array if no matches are found.
findChild
findChild(component, matcher?)
Finds the first direct child element that matches the given component and an optional matcher. Only searches immediate children, not descendants. Throws an error if no match is found.
The non-throwing variant is maybeFindChild().
findAllChildren
findAllChildren(component, matcher?)
Finds all direct child elements that match the given component and an optional matcher. Only searches immediate children, not descendants. This combines the behavior of findAll() (returning all matches) with findChild() (searching only direct children).
maybeFind (non-throwing variants)
The following methods are non-throwing variants that returnnull if no match is found:
maybeFind(component, matcher?)maybeFindChild(component, matcher?)maybeFindByTestId(component, testId)
Element matchers
All query methods accept an optional parameter that can be either of the following:- Props object: match elements with specific prop values.
- Predicate function: match elements using a custom function.
Interacting with components
Accessing element properties
Rendered elements expose several properties:Triggering events
Use thetrigger() method to invoke event handlers:
Async testing
Waiting for async updates
UsewaitFor() to wait for asynchronous updates to the rendered output:
Timeout configuration
By default,waitFor() waits up to 1000ms. You can customize the timeout:
WaitForTimeoutError is thrown.
Mocking
The testing SDK provides comprehensive mocking support for UI extensions to avoid making real API calls and being dependent on HubSpot data. The testing utilities make it easy to control the behavior of provided React hooks, extension point actions, and more. When you create a renderer withcreateRenderer(extensionPointLocation), the testing SDK automatically creates appropriate mocks for the Extension Point API based on the location you specify. Default mock implementations with spies are provided for supported hooks such as useCrmProperties() and useAssociations() and Extension Point API actions such as actions.addAlert().
See the Mocking guide for detailed documentation on mocking, including:
- Automatic mocks based on extension point location
- Mocking
context,actions, andrunServerlessFunction - Available hook mocks (
useCrmProperties(),useAssociations()) - Advanced mock features (spy properties, resetting, etc.)
Working with fragments
Some components allow React nodes to be passed in as part of component props, and these props are treated as “fragment props.” Fragment props are automatically converted toRenderedFragmentNode objects:
Debugging
debugLog
Log a string representation of the rendered output:toString
Get a string representation of a node:getRootNode
Access the root node directly:Type guards
The testing SDK provides type guard functions to help narrow TypeScript types when working with rendered nodes. These are useful when you need to perform type-specific operations on nodes.isRenderedElementNode
Check if a node is a rendered element node:isRenderedTextNode
Check if a node is a rendered text node:isRenderedRootNode
Check if a node is a rendered root node:isRenderedFragmentNode
Check if a node is a rendered fragment node:isMatch
Check if a node matches a specific component and optional matcher criteria. This is particularly useful when iterating over child nodes where you need to check the type and properties of each node. TheisMatch function is available in two ways:
- As a standalone exported function: useful for checking nodes when iterating over child nodes
- As a method on all rendered nodes: convenient for chaining from an already-found node
Standalone function
Node method
All rendered nodes (includingRenderedRootNode, RenderedFragmentNode, RenderedElementNode, and RenderedTextNode) have an isMatch method:
Error handling
The testing SDK throws specific errors for different scenarios:InvalidComponentsError: when invalid component types are detected in the rendered output.WaitForTimeoutError: when awaitFor()check doesn’t pass within the timeout period.MissingEventFunctionError: when triggering an event that doesn’t have a handler.InvalidEventFunctionError: when triggering an event whose handler is not a function.ComponentNotFoundByTestIdError: when a component with the specifiedtestIdis not found in the rendered output.ComponentMismatchedByTestIdError: when atestIdexists but the component type doesn’t match the expected component.DuplicateTestIdError: when attempting to render multiple components with the sametestId.