From 1a1331f511c10ba2190a618144799113cf3d8403 Mon Sep 17 00:00:00 2001 From: Lukas Engelter Date: Tue, 11 Feb 2025 23:04:25 +0100 Subject: [PATCH 1/6] test: add back button test --- test/src/introduction_screen_test.dart | 30 +++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/src/introduction_screen_test.dart b/test/src/introduction_screen_test.dart index a746e7d..6b49e2f 100644 --- a/test/src/introduction_screen_test.dart +++ b/test/src/introduction_screen_test.dart @@ -1,6 +1,6 @@ import 'package:dots_indicator/dots_indicator.dart'; -import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:introduction_screen/introduction_screen.dart'; void main() { @@ -12,6 +12,8 @@ void main() { bool showSkipButton = false, bool showDoneButton = false, bool showNextButton = true, + bool showBackButton = false, + int initialPage = 0, int? autoScrollDuration, }) { return MaterialApp( @@ -24,8 +26,11 @@ void main() { next: showNextButton ? Text("Next") : null, showSkipButton: showSkipButton, showDoneButton: showDoneButton, + showBackButton: showBackButton, + back: showBackButton ? Text("Back") : null, showNextButton: showNextButton, autoScrollDuration: autoScrollDuration, + initialPage: initialPage, ), ); } @@ -64,6 +69,29 @@ void main() { expect(find.text('Page 2'), findsOneWidget); }); + testWidgets('Back button goes back to the previous page', (tester) async { + // Arrange + await tester.pumpWidget(createIntroductionScreen( + pages: [ + PageViewModel(title: 'Page 1', body: 'Introduction 1'), + PageViewModel(title: 'Page 2', body: 'Introduction 2'), + ], + showBackButton: true, + initialPage: 1, + )); + + expect(find.text('Page 1'), findsNothing); + expect(find.text('Page 2'), findsOneWidget); + + // Act + await tester.tap(find.text('Back')); + await tester.pumpAndSettle(); + + // Assert + expect(find.text('Page 1'), findsOneWidget); + expect(find.text('Page 2'), findsNothing); + }); + testWidgets('Skip button triggers onSkip callback', (tester) async { // Arrange var skipTapped = false; From a2e506642445817aced588d1f3ac326343f3f031 Mon Sep 17 00:00:00 2001 From: Lukas Engelter Date: Tue, 11 Feb 2025 23:37:48 +0100 Subject: [PATCH 2/6] test: improve auto-scroll test to verify that only one page is advanced at a time --- test/src/introduction_screen_test.dart | 40 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/test/src/introduction_screen_test.dart b/test/src/introduction_screen_test.dart index 6b49e2f..e614f9e 100644 --- a/test/src/introduction_screen_test.dart +++ b/test/src/introduction_screen_test.dart @@ -195,24 +195,40 @@ void main() { }); }); - testWidgets('Auto-scroll works as expected', (WidgetTester tester) async { + testWidgets('Auto-scroll advances one page at a time', + (WidgetTester tester) async { // Arrange - final pages = [ - PageViewModel(title: 'Page 1', body: 'Introduction 1'), - PageViewModel(title: 'Page 2', body: 'Introduction 2'), - ]; - - await tester.pumpWidget( - createIntroductionScreen(pages: pages, autoScrollDuration: 5)); + const autoScrollDuration = 2000; + await tester.pumpWidget(createIntroductionScreen( + pages: [ + PageViewModel(title: 'Page 1', body: 'Introduction 1'), + PageViewModel(title: 'Page 2', body: 'Introduction 2'), + PageViewModel(title: 'Page 3', body: 'Introduction 3'), + ], + autoScrollDuration: autoScrollDuration, + )); - // Initial page should be Page 1 + // Should still be at page 1 after 100 ms + await tester.pump(Duration(milliseconds: 100)); + await tester.pumpAndSettle(); expect(find.text('Page 1'), findsOneWidget); + expect(find.text('Page 2'), findsNothing); + expect(find.text('Page 3'), findsNothing); - // Simulate time passing to trigger auto-scroll - await tester.pump(const Duration(milliseconds: 10)); + // Wait for first auto-scroll, should be on page 2 now + await tester.pump(Duration(milliseconds: autoScrollDuration + 100)); await tester.pumpAndSettle(); - // The auto-scroll should have moved to the next page + expect(find.text('Page 1'), findsNothing); expect(find.text('Page 2'), findsOneWidget); + expect(find.text('Page 3'), findsNothing); + + // Wait for second auto-scroll, should be on page 3 now + await tester.pump(Duration(milliseconds: autoScrollDuration)); + await tester.pumpAndSettle(); + + expect(find.text('Page 1'), findsNothing); + expect(find.text('Page 2'), findsNothing); + expect(find.text('Page 3'), findsOneWidget); }); } From a0cd8172fd77463870b7066c232b72dc1e3155a2 Mon Sep 17 00:00:00 2001 From: Lukas Engelter Date: Tue, 11 Feb 2025 23:38:01 +0100 Subject: [PATCH 3/6] test: simplify helper tests --- test/src/helper_test.dart | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/test/src/helper_test.dart b/test/src/helper_test.dart index 64cef0b..67e2dc5 100644 --- a/test/src/helper_test.dart +++ b/test/src/helper_test.dart @@ -4,31 +4,26 @@ import 'package:introduction_screen/src/helper.dart'; void main() { // Global variables final originalList = [1, 2, 3, 4, 5]; - final list = ['a', 'b', 'c']; group('CustomList', () { - test('asReversed returns reversed list when isReverse is true', () { - final reversedList = originalList.asReversed(true); - - expect(reversedList, [5, 4, 3, 2, 1]); + test('asReversed() reverses list when isReverse is true', () { + expect(originalList.asReversed(true), [5, 4, 3, 2, 1]); }); - test('asReversed returns original list when isReverse is false', () { - final originalCopy = originalList.asReversed(false); - - expect(originalCopy, originalList); + test('asReversed() returns original list when isReverse is false', () { + expect(originalList.asReversed(false), [1, 2, 3, 4, 5]); }); test('elementAtOrNull returns the correct element for valid index', () { - expect(list.elementAtOrNull(1), 'b'); + expect(originalList.elementAtOrNull(1), 2); }); test('elementAtOrNull returns null for out of bounds index', () { - expect(list.elementAtOrNull(5), isNull); + expect(originalList.elementAtOrNull(5), isNull); }); test('elementAtOrNull returns null for negative index', () { - expect(list.elementAtOrNull(-1), isNull); + expect(originalList.elementAtOrNull(-1), isNull); }); }); } From 6858973bafd5a1266c8fe474212c8a759f57446c Mon Sep 17 00:00:00 2001 From: Lukas Engelter Date: Wed, 12 Feb 2025 00:35:49 +0100 Subject: [PATCH 4/6] fix(IntroButton): ensure that all button styles can be overriden TextButton style merge is implemented in a way that the original object takes precedence over the argument. We therefore switch the merge orientation to ensure that it is possible to override every style. Closes #224 --- lib/src/ui/intro_button.dart | 12 +++++++----- test/widget/intro_ui_test.dart | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/src/ui/intro_button.dart b/lib/src/ui/intro_button.dart index 94e6c96..759b82b 100644 --- a/lib/src/ui/intro_button.dart +++ b/lib/src/ui/intro_button.dart @@ -16,6 +16,12 @@ class IntroButton extends StatelessWidget { @override Widget build(BuildContext context) { + final defaultStyle = TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ); + return MergeSemantics( child: Semantics( label: semanticLabel, @@ -23,11 +29,7 @@ class IntroButton extends StatelessWidget { child: TextButton( onPressed: onPressed, child: child, - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - ).merge(style), + style: style?.merge(defaultStyle) ?? defaultStyle, ), ), ); diff --git a/test/widget/intro_ui_test.dart b/test/widget/intro_ui_test.dart index 35023a9..efef456 100644 --- a/test/widget/intro_ui_test.dart +++ b/test/widget/intro_ui_test.dart @@ -125,5 +125,37 @@ void main() { // Check that the image is rendered expect(find.byWidget(mockImage), findsOneWidget); }); + + testWidgets('IntroButton custom styles override default styles', + (tester) async { + // Create a custom style with a different border radius + final customStyle = TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(20.0), // Different from default 8.0 + ), + backgroundColor: Colors.blue, // Additional property to verify + ); + + await tester.pumpWidget(testableWidget( + child: IntroButton( + child: const Text('Test Text'), + style: customStyle, + ), + )); + + // Find the TextButton + final button = tester.widget(find.byType(TextButton)); + + // Get the shape from the button's style + final shape = button.style?.shape?.resolve({}); + expect(shape, isA()); + final borderRadius = (shape as RoundedRectangleBorder).borderRadius; + expect(borderRadius, BorderRadius.circular(20.0)); + + // Verify the background color was also applied + final backgroundColor = button.style?.backgroundColor?.resolve({}); + expect(backgroundColor, Colors.blue); + }); }); } From 12b206c294d63ec6d1f082af83e53c175f81013f Mon Sep 17 00:00:00 2001 From: Lukas Engelter Date: Wed, 12 Feb 2025 00:42:15 +0100 Subject: [PATCH 5/6] chore(release): bump version to 3.1.15 --- CHANGELOG.md | 5 +++++ README.md | 2 +- pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d2119..7085a4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.1.15] - 2025-02-12 + +### Fixed +- Fix button style can not be overridden [#224](https://github.com/Pyozer/introduction_screen/pull/224) + ## [3.1.14] - 2024-03-23 ### Fixed diff --git a/README.md b/README.md index 24c9cdf..3b1f5d2 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ You just need to add `introduction_screen` as a [dependency in your pubspec.yaml ```yaml dependencies: - introduction_screen: ^3.1.14 + introduction_screen: ^3.1.15 ``` ## Examples diff --git a/pubspec.yaml b/pubspec.yaml index 5857771..2967275 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: introduction_screen description: Introduction/Onboarding package for flutter app with some customizations possibilities -version: 3.1.14 +version: 3.1.15 repository: https://github.com/pyozer/introduction_screen issue_tracker: https://github.com/pyozer/introduction_screen/issues From f758b550e467cb58e2515d5658e408a3b63c97d9 Mon Sep 17 00:00:00 2001 From: Lukas Engelter Date: Wed, 12 Feb 2025 10:47:59 +0100 Subject: [PATCH 6/6] chore(Example): upgrade Gradle and Android Gradle Plugin versions to support current flutter / dart version Update Android build tooling: - Bump Android Gradle Plugin from 7.3.0 to 8.1.0 - Upgrade Gradle wrapper from 7.6.3 to 8.0 --- .github/workflows/example_app.yml | 2 +- example/android/gradle/wrapper/gradle-wrapper.properties | 2 +- example/android/settings.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/example_app.yml b/.github/workflows/example_app.yml index ac2a8e2..820a5d3 100644 --- a/.github/workflows/example_app.yml +++ b/.github/workflows/example_app.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '11' + java-version: '17' - run: dart --version - run: flutter --version - run: flutter analyze diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index e1ca574..8bc9958 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 1d6d19b..0f9d8c9 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false + id "com.android.application" version "8.1.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false }