moviestar

MovieStar E2E Testing Guide

This guide explains how to write, run, and debug end-to-end (E2E) integration tests for the MovieStar application. The testing framework supports both quick automated testing and interactive visual testing.

New to POD authentication? Read Understanding POD Authentication first to learn why OAuth, DPoP, and browser automation are necessary.

Documentation index: See README.md for complete documentation navigation.

Quick Start

# Extract auth data (first time only)
dart run integration_test/tools/generate_auth_data.dart

# Run all tests quickly
make qtest

# Run specific test
make workflows/pod_favorites_real_test.qtest

Table of Contents

Test Types

Integration Tests

End-to-end tests that run the complete application and verify functionality:

Basic Tests:

Workflow Tests:

Visual Rendering Pattern

All integration tests follow a consistent pattern to ensure UI is fully rendered before testing:

Steps:

Example from app_hive_test.dart:

await tester.pumpWidget(...);
await tester.pumpAndSettle(const Duration(seconds: 5));
await tester.pump(interact);  // 0s in qtest, 5s in itest

Example from pod_favorites_real_test.dart:

await tester.pumpWidget(...);
await tester.pumpAndSettle(const Duration(seconds: 5));
await Future.delayed(delay);  // Allow styling to load
await tester.pump();
await tester.pump(interact);

This ensures tests work reliably in both quick (INTERACT=0) and interactive (INTERACT>0) modes.

Unit Tests

Component-level tests for individual widgets, services, and state management in test/ directory.

Running Tests

IMPORTANT: Do not use flutter test integration_test/ (batch mode) on desktop platforms - it fails due to a Flutter framework limitation. Use make qtest instead, which runs tests individually.

Quick Test Mode (qtest)

Run all tests quickly without visual interaction:

# Run all integration tests (recommended)
make qtest

# Run specific test
make workflows/pod_favorites_real_test.qtest

Features:

Interactive Test Mode (itest)

Run tests with visual interaction delays:

# Run specific test interactively
make workflows/pod_favorites_real_test.itest

# Or use flutter test with INTERACT parameter
flutter test integration_test/workflows/pod_favorites_real_test.dart \
  -d linux --dart-define=INTERACT=5

Features:

Individual Test Modes

# Quick (0s interact)
flutter test integration_test/app_test.dart \
  -d linux --dart-define=INTERACT=0

# Visual review (2s interact)
flutter test integration_test/app_test.dart \
  -d linux --dart-define=INTERACT=2

# Slow/development (5-10s interact)
flutter test integration_test/app_test.dart \
  -d linux --dart-define=INTERACT=10

Writing Tests

The INTERACT Pattern

All tests should use the interact delay from utils/delays.dart:

import '../utils/delays.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('my test', (WidgetTester tester) async {
    // Initialize app
    app.main();
    await tester.pumpAndSettle();

    // Interactive delay
    await tester.pump(interact);

    // Continue with test assertions
    expect(find.text('Movie Star'), findsWidgets);
  });
}

Key Points:

Test Structure Template

/// Brief description of what this test verifies.
///
/// Copyright (C) 2025, Software Innovation Institute, ANU.

library;

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

import 'package:moviestar/main.dart' as app;
import '../utils/delays.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('descriptive test name', (tester) async {
    // 1. Setup
    app.main();
    await tester.pumpAndSettle();
    await tester.pump(interact);

    // 2. Actions
    // ... perform user actions ...

    // 3. Assertions
    expect(/* condition */, /* matcher */);
  });
}

POD Authentication

Complete Auth Data vs Legacy Tokens

The solidpod package requires complete authentication data including:

Legacy token injection (basic access_token/id_token only) will fail with:

OpenIdException(invalid_grant): grant request is invalid

Extracting Complete Auth Data

Uses browser automation with Puppeteer:

dart run integration_test/tools/generate_auth_data.dart

What it does:

Requirements:

Method 2: Manual Extraction

For visual login or when automation fails:

flutter run integration_test/tools/generate_auth_data.dart -d linux

Steps:

Test Credentials Setup

Create integration_test/fixtures/test_credentials.json:

{
  "username": "your-pod-username",
  "password": "your-pod-password",
  "securityKey": "your-security-key",
  "podUrl": "https://pods.dev.solidcommunity.au/your-pod/",
  "issuer": "https://pods.dev.solidcommunity.au"
}

Security Note: This file is git-ignored. Never commit credentials to version control.

Auto-Regeneration

Tests can automatically regenerate expired tokens:

await CredentialInjector.injectFullAuth(
  autoRegenerateOnFailure: true
);

This will:

Best Practices

Quick Reference

# Run all tests quickly
make qtest.all

# Run specific test quickly
make workflows/pod_favorites_real_test.qtest

# Run specific test interactively
make workflows/pod_favorites_real_test.itest

# Extract auth data (automated)
dart run integration_test/tools/generate_auth_data.dart

# Extract auth data (manual)
flutter run integration_test/tools/generate_auth_data.dart -d linux

# Run with custom INTERACT
flutter test integration_test/app_test.dart \
  -d linux --dart-define=INTERACT=5

# Check test discovery
flutter test --list

See Also

Additional Resources

Documentation

Packages and Tools

Cryptography and Security

Browser Automation