> For the complete documentation index, see [llms.txt](https://docs.abtasty.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.abtasty.com/server-side/sdks/flutter/flutter/abtasty-qa-assistant.md).

# ABTasty QA Assistant

This package allows QA teams and developers to easily test campaigns, force variations, and verify flag values in real-time within their Flutter applications. [Using ABTasty QA Assistant](/server-side/integrations/using-abtasty-qa-assistant.md)

### Table of Contents

* Overview
* Features
* Prerequisites
* Installation
* Quick Start
* Detailed Integration
  * Initialize Flagship SDK
  * Setup QA Assistant
  * Display Overlay Button
  * Live Flag Updates
* Key Features
* Best Practices
* Troubleshooting
* Additional Resources

***

### Overview

The ABTasty QA Assistant provides an intuitive in-app interface for testing A/B campaigns, feature flags, and variations during development and QA phases. It seamlessly integrates with the Flagship Flutter SDK to provide real-time flag updates and comprehensive campaign management.

#### ⚠️ Production Warning

{% hint style="warning" %}
**Do not ship this package to production!** The QA Assistant is intended for development and QA testing only.
{% endhint %}

To prevent accidental inclusion in production, wrap the QA Assistant initialization with a debug check:

```dart
import 'package:flutter/foundation.dart';

void _toggleQAAssistant() {
  if (kDebugMode) {  // Only available in debug mode
    if (_qaAssistant == null) {
      _qaAssistant = ABTastyQAAssistant(...);
      _qaAssistant?.showOverlayButton(context);
    }
  }
}
```

***

### Features

* 🎯 **Campaign Management** - View, test, and force variations for A/B tests and feature flags
* 🔄 **Live Flag Updates** - Real-time flag value changes when forcing variations
* 📊 **Allocation Viewer** - Check traffic distribution across variations
* 🎨 **Overlay Button** - Floating button for easy access during testing
* 🔍 **Targeting Inspection** - Verify targeting rules and conditions
* 📈 **Event Tracking** - Monitor all events sent to Flagship
* 🧪 **Variation Testing** - Force specific variations to test different experiences

***

### Prerequisites

Before integrating the ABTasty QA Assistant, ensure you have:

* Flutter SDK installed (>=3.6.1)
* An ABTasty account with:
  * Environment ID
  * API Key
* The Flutter [Flagship SDK v4.3.0](/server-side/sdks/flutter/flutter.md) installed in your project

***

### Installation

#### Step 1: Add Dependencies

Add both the Flagship SDK and QA Assistant to your `pubspec.yaml`:

```yaml
dependencies:
  flutter:
    sdk: flutter
    
  # Flagship SDK
  flagship: ^4.3.0
  
  # ABTasty QA Assistant
  abtasty_qa_assistant: ^1.0.0
```

#### Step 2: Install Packages

Run the following command:

```bash
flutter pub get
```

***

### Quick Start

Get up and running in 5 minutes with this complete example:

#### Step 1: Replace Your Credentials

Replace these placeholders with your actual values:

* `YOUR_ENVIRONMENT_ID` - Your Flagship environment ID
* `YOUR_API_KEY` - Your Flagship API key

#### Step 2: Copy & Paste This Code

```dart
import 'package:flutter/material.dart';
import 'package:flagship/flagship.dart';
import 'package:abtasty_qa_assistant/abtasty_qa_assistant.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ABTasty QA Demo',
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  ABTastyQAAssistant? _qaAssistant;
  String _flagValue = "Loading...";

  @override
  void initState() {
    super.initState();
    _initFlagship();
  }

  Future<void> _initFlagship() async {
    // 1. Initialize Flagship
    await Flagship.start(
      "YOUR_ENVIRONMENT_ID",
      "YOUR_API_KEY",
    );

    // 2. Create a visitor
    Flagship.newVisitor(
      visitorId: "user_123",
      hasConsented: true,
    ).withContext({
      "isQA": true,
    }).build();

    // 3. Fetch flags
    await Flagship.getCurrentVisitor()?.fetchFlags();

    // 4. Setup live updates
    Flagship.getCurrentVisitor()?.onFlagUpdate = (changedKeys) {
      print('🔔 Flags updated: $changedKeys');
      _updateFlagValue();
    };

    _updateFlagValue();
  }

  void _updateFlagValue() {
    setState(() {
      _flagValue = Flagship.getCurrentVisitor()
          ?.getFlag("btnTitle")
          .value("Default Button") ?? "No value";
    });
  }

  void _toggleQA() {
    if (_qaAssistant == null) {
      _qaAssistant = ABTastyQAAssistant(
        "YOUR_ENVIRONMENT_ID",
        "YOUR_API_KEY",
        onClose: () {
          print('QA Assistant closed');
        },
      );
      _qaAssistant?.showOverlayButton(context);
    } else {
      _qaAssistant?.hideOverlayButton();
      _qaAssistant?.dispose();
      _qaAssistant = null;
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ABTasty QA Demo'),
        leading: IconButton(
          icon: Icon(
            _qaAssistant?.isOverlayVisible ?? false
                ? Icons.visibility_off
                : Icons.bug_report,
          ),
          onPressed: _toggleQA,
          tooltip: 'Toggle QA Assistant',
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'Flag Value:',
              style: TextStyle(fontSize: 18),
            ),
            const SizedBox(height: 8),
            Text(
              _flagValue,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: Colors.blue,
              ),
            ),
            const SizedBox(height: 32),
            ElevatedButton(
              onPressed: _toggleQA,
              child: Text(
                _qaAssistant?.isOverlayVisible ?? false
                    ? 'Hide QA Assistant'
                    : 'Show QA Assistant',
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    Flagship.getCurrentVisitor()?.onFlagUpdate = null;
    _qaAssistant?.dispose();
    super.dispose();
  }
}
```

#### Step 3: Run Your App

```bash
flutter run
```

#### Step 4: Use the QA Assistant

1. **Tap the bug icon** in the AppBar (top-left)
2. **The QA overlay button appears** in the bottom-right corner
3. **Tap the overlay button** to open the QA Assistant dialog
4. **Browse campaigns** and force different variations
5. **Watch the flag value update live** when you select variations

***

### Detailed Integration

#### 1. Initialize Flagship SDK

First, initialize the Flagship SDK in your app:

```dart
Future<void> _initFlagship() async {
  try {
    // Start Flagship SDK
    await Flagship.start(
      "YOUR_ENVIRONMENT_ID",
      "YOUR_API_KEY",
    );

    // Create a visitor with context
    Flagship.newVisitor(
      visitorId: "user_123",
      hasConsented: true,
    ).withContext({
      "isQA": true,
      "country": "FR",
      "isVip": false,
      // Add your custom context
    }).build();

    print("✅ Flagship SDK initialized");

    // Fetch flags from the server
    await Flagship.getCurrentVisitor()?.fetchFlags();
    
  } catch (e) {
    print("❌ Error initializing Flagship: $e");
  }
}
```

#### 2. Setup QA Assistant

Initialize the QA Assistant with your credentials:

```dart
void _initializeQAAssistant() {
  _qaAssistant = ABTastyQAAssistant(
    "YOUR_ENVIRONMENT_ID",
    "YOUR_API_KEY",
    onClose: () {
      // Called when QA Assistant dialog is closed
      print('🔄 QA Assistant closed, refreshing flags...');
      _refreshFlags();
    },
  );
  
  print('✅ QA Assistant initialized');
}
```

#### 3. Display Overlay Button

Show the floating overlay button in your app:

```dart
void _showQAAssistant() {
  _initializeQAAssistant();
  _qaAssistant?.showOverlayButton(context);
}

void _hideQAAssistant() {
  _qaAssistant?.hideOverlayButton();
  _qaAssistant?.dispose();
  _qaAssistant = null;
}

void _toggleQAAssistant() {
  if (_qaAssistant?.isOverlayVisible ?? false) {
    _hideQAAssistant();
  } else {
    _showQAAssistant();
  }
  setState(() {});
}
```

**Add a button in your AppBar:**

```dart
AppBar(
  title: const Text('My App'),
  leading: IconButton(
    icon: Icon(
      _qaAssistant?.isOverlayVisible ?? false
          ? Icons.visibility_off
          : Icons.bug_report,
    ),
    onPressed: _toggleQAAssistant,
    tooltip: 'Toggle QA Assistant',
  ),
)
```

#### 4. Live Flag Updates

Enable live flag updates to automatically refresh your UI when flags are modified through the QA Assistant:

```dart
void _setupFlagUpdateListener() {
  final visitor = Flagship.getCurrentVisitor();
  if (visitor != null) {
    visitor.onFlagUpdate = (changedKeys) {
      print('🔔 Live update received for flags: $changedKeys');
      
      // Show notification
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('🔄 Live update: ${changedKeys.join(", ")}'),
            backgroundColor: Colors.orange,
            duration: const Duration(seconds: 2),
          ),
        );
      }
      
      // Update your UI with new flag values
      _updateFlagValues();
    };
    
    print('✅ Flag update listener registered');
  }
}

void _updateFlagValues() {
  final visitor = Flagship.getCurrentVisitor();
  if (visitor != null) {
    setState(() {
      // Get updated flag values
      final buttonTitle = visitor.getFlag("btnTitle").value("Default");
      final buttonColor = visitor.getFlag("btnColor").value("blue");
      
      print("Updated flag values:");
      print("  btnTitle: $buttonTitle");
      print("  btnColor: $buttonColor");
    });
  }
}
```

**Important:** Setup the listener AFTER creating the visitor:

```dart
Future<void> _initFlagship() async {
  await Flagship.start("ENV_ID", "API_KEY");
  
  Flagship.newVisitor(visitorId: "user_123", hasConsented: true)
    .withContext({"isQA": true})
    .build();
    
  await Flagship.getCurrentVisitor()?.fetchFlags();
  
  // ✅ Setup listener after visitor is created
  _setupFlagUpdateListener();
}
```

***

### Key Features

#### 🎯 Campaign Management

The QA Assistant provides a comprehensive interface to:

* **View all campaigns** - See active, inactive, and forced campaigns (A/B tests, toggles, personalizations)
* **View variations** - Explore different variations for each campaign with all associated flags
* **Force variations** - Override the default allocation and test specific variations
* **Reset to original** - Return to the production variation with a single tap
* **View allocations** - Check traffic distribution across variations
* **Check targeting** - Verify targeting rules and conditions

{% hint style="info" %}
See [Using ABTasty QA Assistant](/server-side/integrations/using-abtasty-qa-assistant.md) for more information
{% endhint %}

#### 🔄 Live Flag Updates

Real-time flag value changes when you force variations through the QA Assistant:

```dart
// Setup listener for automatic UI updates
Flagship.getCurrentVisitor()?.onFlagUpdate = (changedKeys) {
  print('🔔 Flags updated: $changedKeys');
  setState(() {
    // Refresh your UI with new flag values
  });
};
```

#### 📊 Comprehensive Views

* **Variations Tab** - See all flags and their values for each variation
* **Allocation Tab** - View traffic distribution percentages
* **Targeting Tab** - Check targeting rules and audience criteria
* **Dashboard Tab** - See campaign state and status
* **Events Tab** - Monitor events sent to Flagship in real-time

#### 🔍 Context Management

* **View current context** - See all context key-value pairs for the visitor
* **Modify context** - Update context values for testing different targeting scenarios

***

### Best Practices

#### 1. Initialize in Debug Mode Only

Only enable the QA Assistant in debug/staging environments:

```dart
import 'package:flutter/foundation.dart';

void _initQAAssistant() {
  if (kDebugMode || _isStagingEnvironment) {
    _qaAssistant = ABTastyQAAssistant(
      "YOUR_ENVIRONMENT_ID",
      "YOUR_API_KEY",
    );
  }
}
```

#### 2. Always Dispose Properly

Clean up resources when the widget is disposed:

```dart
@override
void dispose() {
  final visitor = Flagship.getCurrentVisitor();
  if (visitor != null) {
    visitor.onFlagUpdate = null;  // Remove listener
  }
  
  _qaAssistant?.hideOverlayButton();
  _qaAssistant?.dispose();
  
  super.dispose();
}
```

### Troubleshooting

#### Issue: Overlay button not showing

**Solution:** Make sure you've called `showOverlayButton(context)` with a valid `BuildContext`:

```dart
_qaAssistant?.showOverlayButton(context);
```

#### Issue: Flags not updating after forcing a variation

**Solution:** Ensure the flag update listener is properly registered:

```dart
// Setup listener AFTER creating visitor
_setupFlagUpdateListener();
```

Also verify that `onFlagUpdate` callback is set:

```dart
Flagship.getCurrentVisitor()?.onFlagUpdate = (changedKeys) {
  _updateFlagValues();
};
```

#### Issue: "Allocation has been bypassed" message

This is expected when you force a campaign. The allocation is bypassed because you've manually selected a variation instead of letting the normal traffic allocation decide. This is working as intended.

#### Issue: QA Assistant not compiling in production build

Make sure to wrap QA Assistant code in debug checks:

```dart
import 'package:flutter/foundation.dart';

if (kDebugMode) {
  // QA Assistant code
}
```

{% hint style="info" %}
[Consider using build flavors to completely exclude the package from production builds.](#user-content-fn-1)[^1]
{% endhint %}

***

### Additional Resources

* [Flagship Flutter SDK Documentation](https://docs.developers.flagship.io/docs/flutter)
* [ABTasty Platform Documentation](https://doc.abtasty.com/)
* [Example Application](#example-application)
* [GitHub Repository](https://github.com/flagship-io/abtasty-qa-assistant-flutter)
* [Report Issues](https://github.com/flagship-io/abtasty-qa-assistant-flutter/issues)

***

### Example Application

A complete demo application is included in the `example/` directory. To run it:

```bash
cd example
flutter run
```

The example demonstrates:

* Complete Flagship SDK integration
* QA Assistant setup
* Live flag updates
* Multiple campaign types
* Context management

[^1]:


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.abtasty.com/server-side/sdks/flutter/flutter/abtasty-qa-assistant.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
