Flutter Fixtures Core

pub package

Core interfaces and domain models for the Flutter Fixtures library. This package provides the foundational abstractions that enable extensible fixture-based mocking.

🎯 Purpose

This package defines the core contracts and data models used by all Flutter Fixtures implementations. Use this package when:

  • Creating custom data providers (database, file system, network, etc.)
  • Extending the Flutter Fixtures ecosystem with new data source functionality
  • Building libraries that need fixture-based mocking capabilities

πŸ“¦ What's Included

Interfaces

  • DataSelectorView: Interface for fixture selection components
  • FixtureSelector: Mixin owning the selection flow β€” strategy dispatch, remembered choices, pick deduplication, delays β€” and the serve pipeline (find β†’ select β†’ data), reported as a FixtureOutcome

Data Models

  • FixtureCollection: Container for multiple fixture response options
  • FixtureDocument: Individual fixture response definition

Fixture Sources

  • FixtureSource: Fixture-file IO β€” candidate resolution, JSON decoding, payload loading
  • HttpFixtureSource: Seam for providing HTTP fixtures; adapters consult an ordered list of sources per HttpFixtureRequest
  • HttpFileFixtureSource: The file-backed source β€” maps a request to fixture-file candidates and delegates to FixtureSource
  • OpenApiFixtureSource: The OpenAPI-backed source β€” a 3.x JSON document's response documentation and payload examples become fixtures
  • FixtureAssetLoader: Seam for reading fixture assets (BundleAssetLoader in production)

Selection Strategies

  • DataSelectorType: Enum defining fixture selection strategies
    • random: Randomly select from available fixtures
    • defaultValue: Use the fixture marked as default
    • pick: Let user choose through UI

Response Delays

  • DataSelectorDelay: Class for simulating response delays
    • instant: No delay (0ms)
    • fast: Fast response (~100ms)
    • moderate: Moderate response (~500ms)
    • slow: Slow response (~2000ms)
    • custom(milliseconds): Custom delay duration

πŸš€ Quick Start

Add to your pubspec.yaml:

dependencies:
  flutter_fixtures_core: ^0.3.0

πŸ› οΈ Creating Custom Fixture Providers

A fixture provider is a source: something that turns a domain request into a FixtureCollection and materializes a document's payload. HTTP sources implement HttpFixtureSource (see HttpFileFixtureSource and OpenApiFixtureSource for the built-ins); for any other domain, define a seam of the same shape and drive it with FixtureSelector.serve:

import 'package:flutter_fixtures_core/flutter_fixtures_core.dart';

/// The seam: your domain request in, model objects out.
abstract class CacheFixtureSource {
  Future<FixtureCollection?> find(String cacheKey);
  Future<Object?> data(FixtureDocument document);
}

/// A file-backed adapter built on core's fixture-file IO.
class FileCacheFixtureSource implements CacheFixtureSource {
  FileCacheFixtureSource({String mockFolder = 'assets/fixtures/cache'})
      : _source = FixtureSource(mockFolder: mockFolder);

  final FixtureSource _source;

  @override
  Future<FixtureCollection?> find(String cacheKey) async {
    final json = await _source.resolve(['$cacheKey.json']);
    return json == null ? null : FixtureCollection.fromJson(json);
  }

  @override
  Future<Object?> data(FixtureDocument document) => _source.data(document);
}

/// The consumer mixes in FixtureSelector and runs the pipeline.
class FixtureCache with FixtureSelector {
  FixtureCache({required this.source, required this.selector, this.view});

  final CacheFixtureSource source;
  final DataSelectorType selector;
  final DataSelectorView? view;

  Future<Object?> read(String cacheKey) async {
    final outcome = await serve(
      find: () => source.find(cacheKey),
      data: source.data,
      view: view,
      selector: selector,
    );
    // Map the outcome to your domain's defaults and error policy.
    return outcome is FixtureServed ? outcome.payload : null;
  }
}

serve owns the find β†’ select β†’ data choreography and returns a FixtureOutcome: FixtureNotFound, FixtureEmpty, FixtureCancelled, or FixtureServed (the selected document plus its payload). Remembered choices, pick deduplication, and delays come with the mixin for free.

⏱️ Simulating Response Delays

Use DataSelectorDelay to simulate network latency or other delays:

// Use predefined delays
await selector.select(
  fixture,
  view,
  DataSelectorType.random,
  delay: DataSelectorDelay.moderate, // 500ms delay
);

// Or create custom delays
await selector.select(
  fixture,
  view,
  DataSelectorType.random,
  delay: DataSelectorDelay.custom(1500), // 1.5 second delay
);

// Default is instant (no delay)
await selector.select(
  fixture,
  view,
  DataSelectorType.random,
  // delay defaults to DataSelectorDelay.instant
);

Available Delays

  • DataSelectorDelay.instant - No delay (0ms) - Default
  • DataSelectorDelay.fast - Fast response (~100ms, comparable to fast 4G/5G)
  • DataSelectorDelay.moderate - Moderate response (~500ms, comparable to 3G)
  • DataSelectorDelay.slow - Slow response (~2000ms, comparable to 2G/EDGE)
  • DataSelectorDelay.custom(ms) - Custom delay with specified milliseconds

πŸ“‹ Data Model Reference

FixtureCollection

Container for multiple fixture response options:

final collection = FixtureCollection(
  description: 'User API responses',
  items: [
    FixtureDocument(
      identifier: 'success',
      description: '200 Success',
      defaultOption: true,
      data: {'users': [...]},
    ),
    // ... more fixtures
  ],
);

FixtureDocument

Individual fixture response definition:

final document = FixtureDocument(
  identifier: 'success',           // Unique identifier
  description: '200 Success',      // Human-readable description
  defaultOption: true,             // Whether this is the default choice
  data: {'users': [...]},          // Inline response data
  dataPath: 'users_large.json',    // Or path to external data file
);

DataSelectorType

Fixture selection strategies:

// Always use default fixture
final defaultSelector = DataSelectorType.defaultValue;

// Randomly select fixture
final randomSelector = DataSelectorType.random;

// Let user choose via UI (requires DataSelectorView implementation)
final pickSelector = DataSelectorType.pick;

DataSelectorView

Interface for implementing fixture selection mechanisms:

abstract class DataSelectorView {
  /// Returns the user's choice, or null if cancelled.
  Future<FixtureChoice?> pick(FixtureCollection fixture);
}

This interface is implemented by UI packages to provide user-driven fixture selection. The core package defines the contract, while implementation packages (like flutter_fixtures_ui) provide concrete implementations.

πŸ”— Integration

This package provides the foundation for:

Use this package directly when building custom data providers or extending the Flutter Fixtures ecosystem.

πŸ“š Examples

For complete examples and usage patterns, see the Flutter Fixtures repository.

🀝 Contributing

Contributions are welcome! Please read our contributing guide.

πŸ“„ License

MIT License - see the LICENSE file for details.