Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ analyzer:
exclude:
- bricks/**
- build/**
- "**/*.mocks.dart"

formatter:
page_width: 120
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter_deck/src/controls/actions/actions.dart';
import 'package:flutter_deck/src/controls/controls.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'toggle_drawer_action_test.mocks.dart';

@GenerateNiceMocks([MockSpec<FlutterDeckControlsNotifier>()])
void main() {
group('ToggleDrawerAction', () {
late final FlutterDeckControlsNotifier mockNotifier;

setUp(() {
mockNotifier = MockFlutterDeckControlsNotifier();
});

test('invoke should call toggleDrawer on notifier', () {
ToggleDrawerAction(mockNotifier).invoke(const ToggleDrawerIntent());

verify(mockNotifier.toggleDrawer()).called(1);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter_deck/src/controls/actions/actions.dart';
import 'package:flutter_deck/src/controls/controls.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'toggle_marker_action_test.mocks.dart';

@GenerateNiceMocks([MockSpec<FlutterDeckControlsNotifier>()])
void main() {
group('ToggleMarkerAction', () {
late final FlutterDeckControlsNotifier mockNotifier;

setUp(() {
mockNotifier = MockFlutterDeckControlsNotifier();
});

test('invoke should call toggleMarker on notifier', () {
ToggleMarkerAction(mockNotifier).invoke(const ToggleMarkerIntent());

verify(mockNotifier.toggleMarker()).called(1);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_deck/src/controls/l10n/flutter_deck_localization_notifier.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
group('FlutterDeckLocalizationNotifier', () {
test('update should change value', () {
const localeEn = Locale('en');
const localeEs = Locale('es');

final notifier = FlutterDeckLocalizationNotifier(locale: localeEn, supportedLocales: const [localeEn, localeEs]);

expect(notifier.value, localeEn);
expect(notifier.supportedLocales.length, 2);

notifier.update(localeEs);

expect(notifier.value, localeEs);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_deck/src/controls/localized_shortcut_labeler.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
group('LocalizedShortcutLabeler', () {
testWidgets('getShortcutLabel uses default labeler logic', (tester) async {
await tester.pumpWidget(const MaterialApp(home: SizedBox.shrink()));

final context = tester.element(find.byType(SizedBox));
final localizations = MaterialLocalizations.of(context);

final labeler = LocalizedShortcutLabeler.instance;
final label = labeler.getShortcutLabel(
const SingleActivator(LogicalKeyboardKey.keyA, control: true),
localizations,
);

expect(label, 'Ctrl+A');
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/src/configuration/configuration.dart';
import 'package:flutter_deck/src/flutter_deck_router.dart';
import 'package:flutter_deck/src/plugins/autoplay/autoplay.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'flutter_deck_autoplay_notifier_test.mocks.dart';

@GenerateNiceMocks([MockSpec<FlutterDeckRouter>()])
void main() {
group('FlutterDeckAutoplayNotifier', () {
late MockFlutterDeckRouter mockRouter;

setUp(() {
mockRouter = MockFlutterDeckRouter();

when(mockRouter.currentSlideIndex).thenReturn(0);
when(mockRouter.currentStep).thenReturn(1);
when(mockRouter.slides).thenReturn([
const FlutterDeckRouterSlide(
route: '/1',
widget: SizedBox(),
configuration: FlutterDeckSlideConfiguration(route: '/1'),
),
]);
when(mockRouter.currentSlideConfiguration).thenReturn(const FlutterDeckSlideConfiguration(route: '/1'));
});

test('initial state is correct', () {
final notifier = FlutterDeckAutoplayNotifier(router: mockRouter);

expect(notifier.isPlaying, isFalse);
expect(notifier.isLooping, isFalse);
expect(notifier.autoplayDuration, const Duration(seconds: 5));
});

test('play changes isPlaying to true', () {
final notifier = FlutterDeckAutoplayNotifier(router: mockRouter);

var listenerCalled = false;

notifier
..addListener(() => listenerCalled = true)
..play();

expect(notifier.isPlaying, isTrue);
expect(listenerCalled, isTrue);

notifier.pause();
});

test('pause changes isPlaying to false', () {
final notifier = FlutterDeckAutoplayNotifier(router: mockRouter)..play();

var listenerCalled = false;

notifier
..addListener(() => listenerCalled = true)
..pause();

expect(notifier.isPlaying, isFalse);
expect(listenerCalled, isTrue);
});

test('toggleLooping toggles isLooping', () {
final notifier = FlutterDeckAutoplayNotifier(router: mockRouter);

var listenerCalled = false;

notifier
..addListener(() => listenerCalled = true)
..toggleLooping();

expect(notifier.isLooping, isTrue);
expect(listenerCalled, isTrue);

notifier.toggleLooping();

expect(notifier.isLooping, isFalse);
});

test('updateAutoplayDuration updates duration and restarts if playing', () {
final notifier = FlutterDeckAutoplayNotifier(router: mockRouter)..play();

var listenerCalled = false;

notifier
..addListener(() => listenerCalled = true)
..updateAutoplayDuration(const Duration(seconds: 10));

expect(notifier.autoplayDuration, const Duration(seconds: 10));
expect(listenerCalled, isTrue);
expect(notifier.isPlaying, isTrue);

notifier.pause();
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/src/controls/controls.dart';
import 'package:flutter_deck/src/flutter_deck.dart';
import 'package:flutter_deck/src/flutter_deck_router.dart';
import 'package:flutter_deck/src/plugins/autoplay/autoplay.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'flutter_deck_autoplay_plugin_test.mocks.dart';

class MockBuildContext extends Mock implements BuildContext {}

@GenerateNiceMocks([MockSpec<FlutterDeck>(), MockSpec<FlutterDeckRouter>(), MockSpec<FlutterDeckControlsNotifier>()])
void main() {
group('FlutterDeckAutoplayPlugin', () {
late MockFlutterDeck mockFlutterDeck;
late MockFlutterDeckRouter mockRouter;
late MockFlutterDeckControlsNotifier mockControlsNotifier;

setUp(() {
mockFlutterDeck = MockFlutterDeck();
mockRouter = MockFlutterDeckRouter();
mockControlsNotifier = MockFlutterDeckControlsNotifier();

when(mockFlutterDeck.router).thenReturn(mockRouter);
when(mockFlutterDeck.controlsNotifier).thenReturn(mockControlsNotifier);
when(mockControlsNotifier.controlsVisible).thenReturn(false);
});

test('init and dispose manage listeners', () {
final plugin = FlutterDeckAutoplayPlugin()..init(mockFlutterDeck);
verify(mockControlsNotifier.addListener(any)).called(1);

plugin.dispose();
verify(mockControlsNotifier.removeListener(any)).called(1);
});

testWidgets('wrap provides AutoplayProvider', (tester) async {
final plugin = FlutterDeckAutoplayPlugin()..init(mockFlutterDeck);

await tester.pumpWidget(MaterialApp(home: plugin.wrap(MockBuildContext(), const Text('ChildWidget'))));

expect(find.byType(FlutterDeckAutoplayProvider), findsOneWidget);
expect(find.text('ChildWidget'), findsOneWidget);
});

test('buildControls returns menu items', () {
final plugin = FlutterDeckAutoplayPlugin()..init(mockFlutterDeck);

final controls = plugin.buildControls(MockBuildContext(), (
context, {
required String label,
required VoidCallback? onPressed,
Widget? icon,
bool? closeOnActivate,
}) {
return const SizedBox();
});

expect(controls.length, 1);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/src/flutter_deck_router.dart';
import 'package:flutter_deck/src/plugins/autoplay/autoplay.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';

import 'flutter_deck_autoplay_provider_test.mocks.dart';

@GenerateNiceMocks([MockSpec<FlutterDeckRouter>()])
void main() {
group('FlutterDeckAutoplayProvider', () {
late MockFlutterDeckRouter mockRouter;

setUp(() {
mockRouter = MockFlutterDeckRouter();
});

testWidgets('provides notifier down the tree', (tester) async {
final notifier = FlutterDeckAutoplayNotifier(router: mockRouter);

await tester.pumpWidget(
MaterialApp(
home: FlutterDeckAutoplayProvider(
notifier: notifier,
child: Builder(
builder: (context) {
final providedNotifier = FlutterDeckAutoplayProvider.of(context);
expect(providedNotifier, equals(notifier));
return const SizedBox();
},
),
),
),
);
});

testWidgets('throws if notifier not found', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (context) {
FlutterDeckAutoplayProvider.of(context);
return const SizedBox();
},
),
),
);
expect(tester.takeException(), isAssertionError);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:flutter_deck/src/plugins/flutter_deck_plugin.dart';
import 'package:flutter_test/flutter_test.dart';

class _TestPlugin extends FlutterDeckPlugin {
const _TestPlugin();
}

class _MockBuildContext extends BuildContext {
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

void main() {
group('FlutterDeckPlugin', () {
test('default methods do nothing or return default values', () {
const plugin = _TestPlugin();

final mockContext = _MockBuildContext();

plugin.dispose(); // Should not throw

final controls = plugin.buildControls(mockContext, (
context, {
required String label,
required VoidCallback? onPressed,
Widget? icon,
bool? closeOnActivate,
}) {
return const SizedBox();
});
expect(controls, isEmpty);

final wrappedChild = plugin.wrap(mockContext, const Text('Child'));
expect(wrappedChild, isA<Text>());
});
});
}
Loading