Test utilities for deck.gl layers providing comprehensive testing functionality including lifecycle testing, automated test generation, visual regression testing, and interaction testing. Essential for unit testing deck.gl layers with resource tracking, performance validation, and WebGL context management.
npm install @deck.gl/test-utilsimport {
testLayer,
testInitializeLayer,
generateLayerTests,
TestRunner,
SnapshotTestRunner,
InteractionTestRunner,
getLayerUniforms,
toLowPrecision,
gl,
device
} from "@deck.gl/test-utils";For CommonJS:
const {
testLayer,
testInitializeLayer,
generateLayerTests
} = require("@deck.gl/test-utils");import { testLayer, generateLayerTests } from "@deck.gl/test-utils";
import { ScatterplotLayer } from "@deck.gl/layers";
// Basic layer lifecycle testing
testLayer({
Layer: ScatterplotLayer,
testCases: [
{
title: "Basic scatter plot",
props: {
data: [
{ position: [0, 0], color: [255, 0, 0] },
{ position: [1, 1], color: [0, 255, 0] }
],
getPosition: d => d.position,
getFillColor: d => d.color,
radiusPixels: 5
}
}
]
});
// Automated test generation
const testCases = generateLayerTests({
Layer: ScatterplotLayer,
sampleProps: {
data: [{ position: [0, 0] }],
getPosition: d => d.position
}
});
testLayer({
Layer: ScatterplotLayer,
testCases
});deck.gl Test Utils is built around several key components:
Core testing functionality for deck.gl layer initialization, updates, and resource management. Handles both synchronous and asynchronous layer operations with automatic resource tracking.
function testLayer<LayerT extends Layer>(opts: {
Layer: LayerClass<LayerT>;
viewport?: Viewport;
timeline?: Timeline;
testCases?: LayerTestCase<LayerT>[];
spies?: string[];
onError?: (error: Error, title: string) => void;
}): void;
function testLayerAsync<LayerT extends Layer>(opts: {
Layer: LayerClass<LayerT>;
viewport?: Viewport;
timeline?: Timeline;
testCases?: LayerTestCase<LayerT>[];
spies?: string[];
onError?: (error: Error, title: string) => void;
}): Promise<void>;Simplified testing functions focused on layer initialization without requiring full test cases. Useful for quick validation that a layer can be constructed and initialized without errors.
function testInitializeLayer(opts: {
layer: Layer;
viewport?: Viewport;
onError?: (error: unknown, title: string) => void;
finalize?: boolean;
}): { finalize: () => void } | null;
function testInitializeLayerAsync(opts: {
layer: Layer;
viewport?: Viewport;
onError?: (error: unknown, title: string) => void;
finalize?: boolean;
}): Promise<{ finalize: () => void } | null>;Automatic generation of comprehensive test cases for deck.gl layers, including property validation, data format testing, and accessor function verification.
function generateLayerTests<LayerT extends Layer>(opts: {
Layer: LayerClass<LayerT>;
sampleProps?: Partial<LayerT['props']>;
assert?: (condition: any, comment: string) => void;
onBeforeUpdate?: LayerTestCase<LayerT>['onBeforeUpdate'];
onAfterUpdate?: LayerTestCase<LayerT>['onAfterUpdate'];
runDefaultAsserts?: boolean;
}): LayerTestCase<LayerT>[];Screenshot-based testing that renders scenes and compares against golden images for visual regression detection. Includes platform-specific overrides and diff image generation.
class SnapshotTestRunner extends TestRunner<SnapshotTestCase, DiffImageResult> {
constructor(props: DeckProps, options?: { imageDiffOptions: ImageDiffOptions });
add(testCases: SnapshotTestCase[]): this;
run(options?: Partial<TestOptions<SnapshotTestCase, DiffImageResult>>): Promise<void>;
}
interface SnapshotTestCase {
name: string;
props: DeckProps;
goldenImage: string;
onBeforeRender?: (params: { deck: Deck; layers: Layer[] }) => void;
onAfterRender?: (params: { deck: Deck; layers: Layer[]; done: () => void }) => void;
timeout?: number;
imageDiffOptions?: ImageDiffOptions;
}Event simulation and interaction flow testing for deck.gl applications. Emulates user input events and validates application state changes.
class InteractionTestRunner extends TestRunner<InteractionTestCase, {}> {
constructor(props: DeckProps, options?: {});
add(testCases: InteractionTestCase[]): this;
run(options?: Partial<TestOptions<InteractionTestCase, {}>>): Promise<void>;
}
interface InteractionTestCase {
name: string;
events: InteractionEvent[];
timeout?: number;
context?: any;
onBeforeEvents: (params: { deck: Deck }) => any;
onAfterEvents: (params: { deck: Deck; layers: Layer[]; context: any }) => void;
}Helper functions for WebGL uniform inspection, precision control, and GL context management.
function getLayerUniforms(layer: Layer, blockName?: string): Record<string, UniformValue>;
function toLowPrecision(input: number, precision?: number): number;
function toLowPrecision(input: number[], precision?: number): number[];
function toLowPrecision(input: Record<string, number>, precision?: number): Record<string, number>;
const gl: WebGL2RenderingContext | WebGLRenderingContext | 1;
const device: Device;interface LayerTestCase<LayerT extends Layer> {
title: string;
viewport?: Viewport;
props?: Partial<LayerT['props']>;
updateProps?: Partial<LayerT['props']>;
spies?: string[];
onBeforeUpdate?: (params: { layer: Layer; testCase: LayerTestCase<LayerT> }) => void;
onAfterUpdate?: (params: {
testCase: LayerTestCase<LayerT>;
layer: LayerT;
oldState: any;
subLayers: Layer[];
subLayer: Layer | null;
spies: Record<string, Spy>;
}) => void;
}
interface LayerClass<LayerT extends Layer> {
new (...args: any[]): LayerT;
layerName: string;
defaultProps: any;
}
abstract class TestRunner<TestCaseT extends TestCase, ResultT, ExtraOptions = {}> {
constructor(props: DeckProps, options: ExtraOptions);
add(testCases: TestCaseT[]): this;
run(options?: Partial<TestOptions<TestCaseT, ResultT> & ExtraOptions>): Promise<void>;
abstract runTestCase(testCase: TestCaseT): Promise<void>;
abstract assert(testCase: TestCaseT): Promise<void>;
}
interface TestCase {
name: string;
timeout?: number;
}
interface TestOptions<TestCaseT extends TestCase, ResultT> {
onTestStart: (testCase: TestCaseT) => void;
onTestPass: (testCase: TestCaseT, result: ResultT) => void;
onTestFail: (testCase: TestCaseT, result: ResultT | { error: string }) => void;
timeout: number;
}
type Spy = {
callCount: number;
reset(): void;
};
type UniformValue = number | number[] | boolean | boolean[];