or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

app-wrappers.mdindex.mdmock-apis.mdmsw-integration.mdtest-api-provider.mdtesting-utilities.md
tile.json

mock-apis.mddocs/

Mock APIs

Modern mock implementations of core Backstage APIs with consistent patterns across all API types. The mockApis namespace provides three usage patterns for each API: fake implementations, factory creators, and Jest mock instances.

Capabilities

mockApis Namespace

The modern approach to API mocking in Backstage tests, providing consistent patterns across all core APIs.

/**
 * Modern mock API implementations with three usage patterns:
 * 1. Direct fake implementation: mockApis.config()
 * 2. Factory creator: mockApis.config.factory()  
 * 3. Jest mock instance: mockApis.config.mock()
 */
declare const mockApis: {
  analytics(): AnalyticsApi;
  analytics.factory(): ApiFactory<AnalyticsApi, AnalyticsApi, {}>;
  analytics.mock(partialImpl?: Partial<AnalyticsApi>): ApiMock<AnalyticsApi>;
  
  config(options?: { data?: JsonObject }): ConfigApi;
  config.factory(): ApiFactory<ConfigApi, ConfigApi, {}>;
  config.mock(): ApiMock<ConfigApi>;
  
  discovery(options?: { baseUrl?: string }): DiscoveryApi;
  discovery.factory(): ApiFactory<DiscoveryApi, DiscoveryApi, {}>;
  discovery.mock(): ApiMock<DiscoveryApi>;
  
  identity(options?: IdentityOptions): IdentityApi;
  identity.factory(): ApiFactory<IdentityApi, IdentityApi, {}>;
  identity.mock(): ApiMock<IdentityApi>;
  
  permission(options?: PermissionOptions): PermissionApi;
  permission.factory(): ApiFactory<PermissionApi, PermissionApi, {}>;
  permission.mock(): ApiMock<PermissionApi>;
  
  storage(options?: { data?: JsonObject }): StorageApi;
  storage.factory(): ApiFactory<StorageApi, StorageApi, {}>;
  storage.mock(): ApiMock<StorageApi>;
  
  translation(): TranslationApi;
  translation.factory(): ApiFactory<TranslationApi, TranslationApi, {}>;
  translation.mock(): ApiMock<TranslationApi>;
};

type ApiMock<TApi> = {
  factory: ApiFactory<TApi, TApi, {}>;
} & { [K in keyof TApi]: jest.MockedFunction<TApi[K]> };

Usage Examples:

import { mockApis, TestApiProvider } from "@backstage/test-utils";

// 1. Fake implementation with data
const configApi = mockApis.config({ 
  data: { app: { title: 'Test App' } } 
});

// 2. Factory for TestApiProvider
<TestApiProvider apis={[[configApiRef, mockApis.config.factory()]]}>
  <MyComponent />
</TestApiProvider>

// 3. Jest mock for testing interactions
const mockConfig = mockApis.config.mock();
mockConfig.getString.mockReturnValue('test-value');

Analytics API Mock

Mock implementation for capturing and verifying analytics events.

/**
 * Create mock analytics API that captures events for verification
 * @returns AnalyticsApi implementation that stores captured events
 */
function analytics(): AnalyticsApi;

/**
 * Create analytics API factory for TestApiProvider usage
 * @returns ApiFactory for analytics API
 */
function analytics.factory(): ApiFactory<AnalyticsApi, AnalyticsApi, {}>;

/**
 * Create Jest mock analytics API with configurable behavior
 * @param partialImpl - Partial implementation to override mock behavior
 * @returns Jest mock instance with analytics API methods
 */
function analytics.mock(partialImpl?: Partial<AnalyticsApi>): ApiMock<AnalyticsApi>;

Config API Mock

Mock implementation for Backstage configuration with customizable data.

/**
 * Create mock config API with optional data
 * @param options - Configuration options
 * @param options.data - JSON object representing config data
 * @returns ConfigApi implementation backed by provided data
 */
function config(options?: { data?: JsonObject }): ConfigApi;

/**
 * Create config API factory for TestApiProvider usage
 * @returns ApiFactory for config API
 */
function config.factory(): ApiFactory<ConfigApi, ConfigApi, {}>;

/**
 * Create Jest mock config API
 * @returns Jest mock instance with all ConfigApi methods
 */
function config.mock(): ApiMock<ConfigApi>;

Discovery API Mock

Mock implementation for Backstage service discovery.

/**
 * Create mock discovery API with configurable base URL
 * @param options - Discovery options
 * @param options.baseUrl - Base URL for all discovered services
 * @returns DiscoveryApi implementation
 */
function discovery(options?: { baseUrl?: string }): DiscoveryApi;

/**
 * Create discovery API factory for TestApiProvider usage
 * @returns ApiFactory for discovery API
 */
function discovery.factory(): ApiFactory<DiscoveryApi, DiscoveryApi, {}>;

/**
 * Create Jest mock discovery API
 * @returns Jest mock instance with discovery API methods
 */
function discovery.mock(): ApiMock<DiscoveryApi>;

Identity API Mock

Mock implementation for Backstage user identity.

/**
 * Create mock identity API with user information
 * @param options - Identity configuration
 * @param options.userEntityRef - User entity reference
 * @param options.ownershipEntityRefs - Owned entity references
 * @returns IdentityApi implementation with mock user data
 */
function identity(options?: IdentityOptions): IdentityApi;

/**
 * Create identity API factory for TestApiProvider usage
 * @returns ApiFactory for identity API
 */
function identity.factory(): ApiFactory<IdentityApi, IdentityApi, {}>;

/**
 * Create Jest mock identity API
 * @returns Jest mock instance with identity API methods
 */
function identity.mock(): ApiMock<IdentityApi>;

interface IdentityOptions {
  userEntityRef?: string;
  ownershipEntityRefs?: string[];
  token?: string;
  email?: string;
  displayName?: string;
  picture?: string;
}

Permission API Mock

Mock implementation for Backstage authorization and permissions.

/**
 * Create mock permission API with configurable authorization behavior
 * @param options - Permission configuration
 * @param options.allow - Default allow/deny behavior for all permissions
 * @param options.requestHandler - Custom handler for permission requests
 * @returns PermissionApi implementation
 */
function permission(options?: PermissionOptions): PermissionApi;

/**
 * Create permission API factory for TestApiProvider usage
 * @returns ApiFactory for permission API
 */
function permission.factory(): ApiFactory<PermissionApi, PermissionApi, {}>;

/**
 * Create Jest mock permission API
 * @returns Jest mock instance with permission API methods
 */
function permission.mock(): ApiMock<PermissionApi>;

interface PermissionOptions {
  authorize?: 
    | AuthorizeResult.ALLOW
    | AuthorizeResult.DENY 
    | ((request: EvaluatePermissionRequest) => AuthorizeResult.ALLOW | AuthorizeResult.DENY);
}

Storage API Mock

Mock implementation for Backstage browser storage.

/**
 * Create mock storage API with optional initial data
 * @param options - Storage configuration
 * @param options.data - Initial data for the storage backend
 * @returns StorageApi implementation backed by in-memory storage
 */
function storage(options?: { data?: JsonObject }): StorageApi;

/**
 * Create storage API factory for TestApiProvider usage
 * @returns ApiFactory for storage API
 */
function storage.factory(): ApiFactory<StorageApi, StorageApi, {}>;

/**
 * Create Jest mock storage API
 * @returns Jest mock instance with storage API methods
 */
function storage.mock(): ApiMock<StorageApi>;

Translation API Mock

Mock implementation for Backstage internationalization.

/**
 * Create mock translation API
 * @returns TranslationApi implementation for testing i18n functionality
 */
function translation(): TranslationApi;

/**
 * Create translation API factory for TestApiProvider usage
 * @returns ApiFactory for translation API
 */
function translation.factory(): ApiFactory<TranslationApi, TranslationApi, {}>;

/**
 * Create Jest mock translation API
 * @returns Jest mock instance with translation API methods
 */
function translation.mock(): ApiMock<TranslationApi>;

Legacy Mock APIs (Deprecated)

These individual mock classes are deprecated in favor of the mockApis namespace but remain available for backward compatibility.

MockConfigApi

/**
 * @deprecated Use mockApis.config() instead
 * Thin wrapper around ConfigReader for mocking configuration
 */
class MockConfigApi implements ConfigApi {
  constructor(data: JsonObject);
  
  has(key: string): boolean;
  keys(): string[];
  get<T>(key?: string): T;
  getOptional<T>(key?: string): T | undefined;
  getConfig(key: string): Config;
  getOptionalConfig(key: string): Config | undefined;
  getConfigArray(key: string): Config[];
  getOptionalConfigArray(key: string): Config[] | undefined;
  getNumber(key: string): number;
  getOptionalNumber(key: string): number | undefined;
  getBoolean(key: string): boolean;
  getOptionalBoolean(key: string): boolean | undefined;
  getString(key: string): string;
  getOptionalString(key: string): string | undefined;
  getStringArray(key: string): string[];
  getOptionalStringArray(key: string): string[] | undefined;
}

MockErrorApi

/**
 * Mock implementation of ErrorApi for testing error handling
 */
class MockErrorApi implements ErrorApi {
  constructor(options?: MockErrorApiOptions);
  
  post(error: ErrorApiError, context?: ErrorApiErrorContext): void;
  error$(): Observable<{error: ErrorApiError; context?: ErrorApiErrorContext}>;
  getErrors(): ErrorWithContext[];
  waitForError(pattern: RegExp, timeoutMs?: number): Promise<ErrorWithContext>;
}

interface MockErrorApiOptions {
  collect?: boolean;
}

interface ErrorWithContext {
  error: ErrorApiError;
  context?: ErrorApiErrorContext;
}

MockFetchApi

/**
 * Test helper implementation of FetchApi with configurable behavior
 */
class MockFetchApi implements FetchApi {
  constructor(options?: MockFetchApiOptions);
  
  readonly fetch: typeof crossFetch;
}

interface MockFetchApiOptions {
  baseImplementation?: undefined | 'none' | typeof crossFetch;
  resolvePluginProtocol?: undefined | { 
    discoveryApi: Pick<DiscoveryApi, 'getBaseUrl'> 
  };
  injectIdentityAuth?: undefined | 
    { token: string } | 
    { identityApi: Pick<IdentityApi, 'getCredentials'> };
}

Types

type JsonObject = { [key: string]: any };

interface ApiFactory<TApi, TImpl extends TApi, TDeps extends {}> {
  api: ApiRef<TApi>;
  deps: { [key in keyof TDeps]: ApiRef<TDeps[key]> };
  factory(deps: TDeps): TImpl;
}