snaptest 0.1.0-dev.1 copy "snaptest: ^0.1.0-dev.1" to clipboard
snaptest: ^0.1.0-dev.1 copied to clipboard

Snap photos in your widget tests.

Snaptest #

Powered by Mason melos

Snap photos in your widget tests.

Installation 💻 #

❗ In order to start using Snaptest you must have the Dart SDK installed on your machine.

Install snaptest as a dev dependency:

dart pub add dev:snaptest

Quick Start Guide 🚀 #

0. Add .snaptest to your .gitignore #

Unless you want snapshots checked into version control, add this pattern to your .gitignore file:

**/.snaptest/

This will ignore all .snaptest directories throughout your project.

1. Call snap() in existing tests #

The simplest way to get started is to add snap() calls to your existing widget tests:

import 'package:flutter_test/flutter_test.dart';
import 'package:snaptest/snaptest.dart';

void main() {
  group('My Page', () {
    testWidgets('Loaded State', (tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: MyPage(),
        ),
      );

      expect(find.byType(MyPage), findsOneWidget);
      
      // Just add this line to take a screenshot
      await snap();
    });
  });
}

The screenshot will be saved in a .snaptest directory next to the current test file, using the name of the test.

2. Use snapTest() for dedicated screenshot tests #

For tests specifically designed for screenshots, use snapTest instead of testWidgets. This automatically adds the screenshot tag for easy filtering:

snapTest('Loaded State', (tester) async {
  await tester.pumpWidget(
    const MaterialApp(
      home: MyPage(),
    ),
  );

  expect(find.byType(MyPage), findsOneWidget);
  
  // Take a screenshot - saved as "Loaded State.png"
  await snap();
});

3. Multiple screenshots with custom names #

You can take multiple screenshots in a single test by providing custom names:

snapTest('User interaction flow', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyPage()));
  
  // Take initial screenshot
  await snap('initial_state');

  await tester.tap(find.byType(FloatingActionButton));
  await tester.pumpAndSettle();

  // Take screenshot after interaction
  await snap('after_button_tap');
});

4. Device-specific testing #

Test your UI on different devices by configuring the settings:

snapTest(
  'Multi-device test',
  (tester) async {
    await tester.pumpWidget(const MaterialApp(home: MyPage()));
    await snap();
  },
  settings: SnaptestSettings(
    devices: [
      Devices.ios.iPhone16Pro,
      Devices.android.samsungGalaxyS20,
      const WidgetTesterDevice(), // Default test environment
    ],
  ),
);

This will generate separate screenshots for each device, with device names appended to the filename.

5. Capturing specific widgets #

You can capture screenshots of specific widgets using the from parameter:

snapTest('Card widget only', (tester) async {
  await tester.pumpWidget(
    MaterialApp(
      home: Scaffold(
        body: Center(
          child: Card(
            key: const Key('my-card'),
            child: const Text('Hello World'),
          ),
        ),
      ),
    ),
  );

  // Only capture the card widget
  await snap(
    name: 'card_only',
    from: find.byKey(const Key('my-card')),
  );
});

6. Advanced rendering options #

Configure how screenshots are rendered using SnaptestSettings:

snapTest(
  'Full rendering test',
  (tester) async {
    await tester.pumpWidget(const MaterialApp(home: MyApp()));
    await snap();
  },
  settings: SnaptestSettings.full([
    Devices.ios.iPhone16Pro,
    Devices.android.samsungGalaxyS20,
  ]),
);

Available SnaptestSettings options:

  • devices: List of devices to test on (default: [WidgetTesterDevice()])
  • blockText: Whether to block text rendering for consistent screenshots (default: true)
  • renderImages: Whether to render actual images (default: false)
  • renderShadows: Whether to render shadows (default: false)

Convenience constructors:

  • SnaptestSettings(): Default settings with blocked text and no images/shadows
  • SnaptestSettings.full(devices): Full rendering with images, shadows, and real text

7. Global settings #

You can set global defaults for all tests:

void main() {
  setUpAll(() {
    SnaptestSettings.global = SnaptestSettings(
      devices: [Devices.ios.iPhone16Pro],
      renderShadows: true,
    );
  });

  tearDownAll(() {
    SnaptestSettings.resetGlobal();
  });

  // Your tests here...
}

8. Additional snap() parameters #

The snap() function supports several parameters for customization:

await snap(
  name: 'custom_name',           // Custom filename
  from: find.byKey(key),         // Specific widget to capture
  settings: SnaptestSettings(),  // Override global settings
  pathPrefix: 'screenshots/',    // Custom directory (default: '.snaptest/')
  appendDeviceName: false,       // Don't append device name to filename
);

Helper Scripts #

snaptest comes with with two scripts that you can run from the root of your project.

clean #

dart run snaptest:clean

This script will delete all the screenshots in the .snaptest directories around your project.

assemble #

dart run snaptest:assemble

Will take all the screenshots in the .snaptest directories around your project and assemble them into a .snaptest/assets directory at the root of your project (and potentially do something cool with them in the future 👀)