291 lines
8.7 KiB
Dart
291 lines
8.7 KiB
Dart
// ignore_for_file: avoid_print
|
|
|
|
/*
|
|
* Copyright (c) 2026 Malloc LLC (malloc.io)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:splash_video/splash_video.dart';
|
|
|
|
void main() {
|
|
group('SplashVideoPage Widget Tests', () {
|
|
testWidgets('creates widget with required parameters',
|
|
(WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
onVideoError: (_) {}, // Suppress errors in test
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.byType(SplashVideo), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('validates conflicting nextScreen and onVideoComplete',
|
|
(WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
nextScreen: const Scaffold(body: Text('Next')),
|
|
onVideoComplete: () {},
|
|
),
|
|
),
|
|
);
|
|
|
|
// Should throw ArgumentError
|
|
expect(tester.takeException(), isA<ArgumentError>());
|
|
});
|
|
|
|
testWidgets('validates looping with nextScreen',
|
|
(WidgetTester tester) async {
|
|
final controller = SplashVideoController(loopVideo: true);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
controller: controller,
|
|
nextScreen: const Scaffold(),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.takeException(), isA<ArgumentError>());
|
|
controller.dispose();
|
|
});
|
|
|
|
testWidgets('validates looping with onVideoComplete',
|
|
(WidgetTester tester) async {
|
|
final controller = SplashVideoController(loopVideo: true);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
controller: controller,
|
|
onVideoComplete: () {},
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.takeException(), isA<ArgumentError>());
|
|
controller.dispose();
|
|
});
|
|
|
|
testWidgets('accepts looping without navigation',
|
|
(WidgetTester tester) async {
|
|
final controller = SplashVideoController(loopVideo: true);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
controller: controller,
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
// Should not throw
|
|
expect(tester.takeException(), isNull);
|
|
expect(find.byType(SplashVideo), findsOneWidget);
|
|
|
|
controller.dispose();
|
|
});
|
|
|
|
testWidgets('renders with backgroundColor', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
backgroundColor: Colors.red,
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump();
|
|
expect(find.byType(SplashVideo), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('renders with title overlay', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
titleWidget: const Text('App Title'),
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump();
|
|
expect(find.text('App Title'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('renders with footer overlay', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
footerWidget: const CircularProgressIndicator(),
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump();
|
|
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('renders with custom overlay builder',
|
|
(WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
overlayBuilder: (context) => const Positioned(
|
|
top: 20,
|
|
right: 20,
|
|
child: Text('v1.0.0'),
|
|
),
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump();
|
|
expect(find.text('v1.0.0'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('renders all overlays together', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
titleWidget: const Text('Title'),
|
|
footerWidget: const Text('Footer'),
|
|
overlayBuilder: (context) => const Text('Custom'),
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump();
|
|
expect(find.text('Title'), findsOneWidget);
|
|
expect(find.text('Footer'), findsOneWidget);
|
|
expect(find.text('Custom'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('calls onVideoError callback', (WidgetTester tester) async {
|
|
String? errorMessage;
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/invalid.mp4'),
|
|
onVideoError: (error) {
|
|
errorMessage = error;
|
|
},
|
|
),
|
|
),
|
|
);
|
|
print('onVideoError: $errorMessage');
|
|
// Wait for potential error
|
|
await tester.pumpAndSettle(const Duration(seconds: 3));
|
|
|
|
// Error should be captured (may or may not occur depending on test env)
|
|
// Just verify the callback is wired correctly
|
|
});
|
|
|
|
testWidgets('shows default error UI when no callback provided',
|
|
(WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/invalid.mp4'),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Wait for error to manifest
|
|
await tester.pumpAndSettle(const Duration(seconds: 3));
|
|
|
|
// Should show error icon when video fails (if it fails)
|
|
// In test environment, may not actually load video
|
|
});
|
|
});
|
|
|
|
group('SplashVideoPage Static Methods', () {
|
|
testWidgets('initialize and resume work', (WidgetTester tester) async {
|
|
// These methods affect WidgetsBinding, so we just verify they don't throw
|
|
SplashVideo.initialize();
|
|
SplashVideo.resume();
|
|
|
|
// Should not throw
|
|
expect(true, isTrue);
|
|
});
|
|
});
|
|
|
|
group('SplashVideoPage with Controller', () {
|
|
testWidgets('accepts controller for looping', (WidgetTester tester) async {
|
|
final controller = SplashVideoController(loopVideo: true);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
controller: controller,
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.byType(SplashVideo), findsOneWidget);
|
|
controller.dispose();
|
|
});
|
|
|
|
testWidgets('controller skip updates state', (WidgetTester tester) async {
|
|
final controller = SplashVideoController(loopVideo: true);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: SplashVideo(
|
|
source: AssetSource('assets/videos/splash.mp4'),
|
|
controller: controller,
|
|
onVideoError: (_) {},
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(controller.skipRequested, isFalse);
|
|
await controller.skip();
|
|
expect(controller.skipRequested, isTrue);
|
|
|
|
controller.dispose();
|
|
});
|
|
});
|
|
}
|