Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding test for core of the package #181

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Flutter Package CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Clone repository
uses: actions/checkout@v3

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
cache: true

- name: Flutter version
run: flutter --version

- name: Install dependencies
run: flutter pub get

- name: Verify formatting
run: dart format --output=none --set-exit-if-changed .

- name: Analyze project source
run: flutter analyze

- name: Run tests
run: flutter test -r github
28 changes: 28 additions & 0 deletions .github/workflows/code-cov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Code Coverage

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
- name: Get packages
run: flutter pub get
- name: Generate coverage file
run: flutter test --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
files: ./coverage/lcov.info
flags: flutter
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
.history
.svn/
migrate_working_dir/
coverage/

# IntelliJ related
*.iml
Expand Down
3 changes: 3 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
coverage:
ignore:
- "**._()" # Ignore all private constructors
6 changes: 2 additions & 4 deletions lib/src/built_in/toastification_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ class ToastificationType {
static const error =
ToastificationType._('error', errorColor, Iconsax.close_circle_copy);

// Factory for custom types
static ToastificationType custom(String name, Color color, IconData icon) {
return ToastificationType._(name, color, icon);
}
const factory ToastificationType.custom(
String name, Color color, IconData icon) = ToastificationType._;

static List<ToastificationType> get defaultValues =>
[info, success, warning, error];
Expand Down
2 changes: 1 addition & 1 deletion lib/src/core/toastification.dart
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,11 @@ class Toastification {
OverlayState? overlayState,
AlignmentGeometry? alignment,
Duration? autoCloseDuration,
Duration? animationDuration,
ToastificationAnimationBuilder? animationBuilder,
ToastificationType? type,
ToastificationStyle? style,
Widget? title,
Duration? animationDuration,
Widget? description,
Widget? icon,
Color? primaryColor,
Expand Down
11 changes: 10 additions & 1 deletion lib/src/core/toastification_callbacks.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:toastification/toastification.dart';

/// A set of callbacks that you can provide to a [Toastification] widget.
/// Used to listen for various events in the lifecycle of the [Toastification].
/// All of the callbacks are optional.
///
class ToastificationCallbacks {
class ToastificationCallbacks extends Equatable {
/// Creates a set of callbacks that you can provide to a [Toastification] widget.
const ToastificationCallbacks({
this.onTap,
Expand All @@ -28,4 +29,12 @@ class ToastificationCallbacks {

/// Called when the toast is dismissed by a user gesture (e.g. a swipe).
final ValueChanged<ToastificationItem>? onDismissed;

@override
List<Object?> get props => [
onTap,
onCloseButtonTap,
onAutoCompleteCompleted,
onDismissed,
];
}
36 changes: 24 additions & 12 deletions lib/src/core/toastification_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:toastification/toastification.dart';

const _defaultAlignment = AlignmentDirectional.topEnd;
const _itemAnimationDuration = Duration(milliseconds: 600);
const _defaultWidth = 400.0;
const _defaultClipBehavior = Clip.none;
@visibleForTesting
const defaultAlignment = AlignmentDirectional.topEnd;

@visibleForTesting
const defaultItemAnimationDuration = Duration(milliseconds: 600);

@visibleForTesting
const defaultWidth = 400.0;

@visibleForTesting
const defaultClipBehavior = Clip.none;

typedef ToastificationMarginBuilder = EdgeInsetsGeometry Function(
BuildContext context,
Expand All @@ -24,12 +31,12 @@ typedef ToastificationMarginBuilder = EdgeInsetsGeometry Function(
///
class ToastificationConfig extends Equatable {
const ToastificationConfig({
this.alignment = _defaultAlignment,
this.itemWidth = _defaultWidth,
this.clipBehavior = _defaultClipBehavior,
this.animationDuration = _itemAnimationDuration,
this.animationBuilder = _defaultAnimationBuilderConfig,
this.marginBuilder = _defaultMarginBuilder,
this.alignment = defaultAlignment,
this.itemWidth = defaultWidth,
this.clipBehavior = defaultClipBehavior,
this.animationDuration = defaultItemAnimationDuration,
this.animationBuilder = defaultAnimationBuilderConfig,
this.marginBuilder = defaultMarginBuilder,
this.applyMediaQueryViewInsets = true,
this.maxToastLimit = 10,
});
Expand Down Expand Up @@ -68,6 +75,7 @@ class ToastificationConfig extends Equatable {
Duration? animationDuration,
ToastificationAnimationBuilder? animationBuilder,
ToastificationMarginBuilder? marginBuilder,
int? maxToastLimit,
bool? applyMediaQueryViewInsets,
}) {
return ToastificationConfig(
Expand All @@ -77,6 +85,7 @@ class ToastificationConfig extends Equatable {
animationDuration: animationDuration ?? this.animationDuration,
animationBuilder: animationBuilder ?? this.animationBuilder,
marginBuilder: marginBuilder ?? this.marginBuilder,
maxToastLimit: maxToastLimit ?? this.maxToastLimit,
applyMediaQueryViewInsets:
applyMediaQueryViewInsets ?? this.applyMediaQueryViewInsets,
);
Expand All @@ -89,12 +98,14 @@ class ToastificationConfig extends Equatable {
clipBehavior,
animationDuration,
marginBuilder,
maxToastLimit,
applyMediaQueryViewInsets,
];
}

/// Default animation builder for [Toastification]
Widget _defaultAnimationBuilderConfig(
@visibleForTesting
Widget defaultAnimationBuilderConfig(
BuildContext context,
Animation<double> animation,
Alignment alignment,
Expand All @@ -108,7 +119,8 @@ Widget _defaultAnimationBuilderConfig(
}

/// Default margin builder for [Toastification]
EdgeInsetsGeometry _defaultMarginBuilder(
@visibleForTesting
EdgeInsetsGeometry defaultMarginBuilder(
BuildContext context,
AlignmentGeometry alignment,
) {
Expand Down
19 changes: 10 additions & 9 deletions lib/src/core/toastification_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ class ToastificationManager {
required this.config,
});

/// this is the delay for showing the overlay entry
/// We need this delay because we want to show the item animation after
/// the overlay created
///
/// When we want to show first toast, we need to wait for the overlay to be created
/// and then show the toast item.
@visibleForTesting
static final kCreateOverlayDelay = const Duration(milliseconds: 100);

final Alignment alignment;

final ToastificationConfig config;
Expand All @@ -27,14 +36,6 @@ class ToastificationManager {
/// if the list is empty, the overlay entry will be removed
final List<ToastificationItem> _notifications = [];

/// this is the delay for showing the overlay entry
/// We need this delay because we want to show the item animation after
/// the overlay created
///
/// When we want to show first toast, we need to wait for the overlay to be created
/// and then show the toast item.
final _createOverlayDelay = const Duration(milliseconds: 100);

/// this is the delay for removing the overlay entry
///
/// when we want to remove the last toast, we need to wait for the animation
Expand Down Expand Up @@ -69,7 +70,7 @@ class ToastificationManager {

if (_overlayEntry == null) {
_createNotificationHolder(overlayState);
delay = _createOverlayDelay;
delay = kCreateOverlayDelay;
}

Future.delayed(
Expand Down
51 changes: 51 additions & 0 deletions test/src/built_in/layout/standard/style/factory_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:toastification/toastification.dart';

void main() {
group('StandardToastStyleFactory', () {
test('creates MinimalStandardToastStyle', () {
final style = StandardToastStyleFactory.createStyle(
style: StandardStyle.minimal,
type: ToastificationType.info,
);

expect(style, isA<MinimalStandardToastStyle>());
});

test('creates FilledStandardToastStyle', () {
final style = StandardToastStyleFactory.createStyle(
style: StandardStyle.fillColored,
type: ToastificationType.success,
);

expect(style, isA<FilledStandardToastStyle>());
});

test('creates FlatStandardColoredToastStyle', () {
final style = StandardToastStyleFactory.createStyle(
style: StandardStyle.flatColored,
type: ToastificationType.warning,
);

expect(style, isA<FlatStandardColoredToastStyle>());
});

test('creates FlatStandardToastStyle', () {
final style = StandardToastStyleFactory.createStyle(
style: StandardStyle.flat,
type: ToastificationType.error,
);

expect(style, isA<FlatStandardToastStyle>());
});

test('creates SimpleStandardToastStyle', () {
final style = StandardToastStyleFactory.createStyle(
style: StandardStyle.simple,
type: ToastificationType.info,
);

expect(style, isA<SimpleStandardToastStyle>());
});
});
}
Loading