diff --git a/.github/workflows/on-main.yml b/.github/workflows/on-main.yml new file mode 100644 index 0000000..0011d37 --- /dev/null +++ b/.github/workflows/on-main.yml @@ -0,0 +1,22 @@ +name: CI - On Main + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +# This job is triggered when a new tag is pushed to the main branch. +jobs: + # This job uses the release-please action to create a release PR. + # See https://github.com/googleapis/release-please + release-please: + runs-on: ubuntu-latest + steps: + - uses: googleapis/release-please-action@v4 + with: + manifest-file: "release-please/.release-please-manifest.json" + config-file: "release-please/release-please-config.json" diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml new file mode 100644 index 0000000..9fb967b --- /dev/null +++ b/.github/workflows/on-release.yml @@ -0,0 +1,9 @@ +name: CI - On Release +on: + push: + tags: + - "*" +# jobs: +## This job is triggered when a new tag is pushed to the repository. +## Typically this would be a release from release-please. +## Here you may want to create a build, publish to a package registry, etc. diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..7b9357c --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,57 @@ +name: CI - Pull Request + +on: + pull_request: + # pull_request_target: # Uncomment this line if you are using pull_request_target + +# Pull Request Runs on the same branch will be cancelled +concurrency: + group: ${{ github.head_ref }} + cancel-in-progress: true + +jobs: + code-quality: + runs-on: ubuntu-latest + steps: + # Checkout the repo + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Use the flutter-action to set up flutter, and cache dependencies + - uses: subosito/flutter-action@v2 + with: + cache: true + + # If you have generated code, you may want to run build_runner to generate the code + # - run: dart run build_runner build --delete-conflicting-outputs + + # Uses the flutter-code-quality action to run code quality checks + # This will return a status check to the pull request + - uses: ZebraDevs/flutter-code-quality@v1.0.9 + with: + token: ${{secrets.GITHUB_TOKEN}} + + # You may want to add more jobs here, such as building and testing your code. + # The following commented job is an example of deploying a preview version of your app + # deploy-preview: + # name: Deploy preview version of the storybook on firebase + # needs: code-quality + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # with: + # repository: ${{github.event.pull_request.head.repo.full_name}} + # ref: ${{ github.head_ref }} + # - uses: subosito/flutter-action@v2 + # with: + # cache: true + # - name: Setup flutter + # run: flutter pub get + # - name: Build example app + # run: flutter build web + # - uses: FirebaseExtended/action-hosting-deploy@v0 + # with: + # repoToken: "${{ secrets.GITHUB_TOKEN }}" + # firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_ZETA_DS }}" + # channelId: "pr-${{ github.event.number }}-${{ github.event.pull_request.head.ref }}" diff --git a/lib/main.dart b/lib/main.dart index cb59c45..65d0904 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,10 +3,12 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'package:zeta_flutter_template/src/utils/routes.dart'; +// coverage:ignore-start void main() async { WidgetsFlutterBinding.ensureInitialized(); runApp(const MyApp()); } +// coverage:ignore-end class MyApp extends StatefulWidget { const MyApp({super.key}); diff --git a/lib/src/pages/example.dart b/lib/src/pages/example.dart index 75c7fb3..81b978f 100644 --- a/lib/src/pages/example.dart +++ b/lib/src/pages/example.dart @@ -57,7 +57,7 @@ class _ExamplePageState extends State { child: Row( children: [ ZetaButton( - label: 'Button', + label: 'Open Dialog', onPressed: () { showZetaDialog( context, @@ -199,10 +199,10 @@ class _ExamplePageState extends State { child: Row( children: [ SizedBox(width: 250, child: ZetaDateInput(label: 'Date Input')), - const SizedBox(width: 250, child: ZetaPasswordInput(label: 'Password input')), - const SizedBox(width: 250, child: ZetaPhoneInput(label: 'Phone Input')), - const SizedBox(width: 250, child: ZetaTimeInput(label: 'Phone Input')), - const SizedBox(width: 250, child: ZetaTextInput(label: 'Phone Input')), + SizedBox(width: 250, child: ZetaPasswordInput(label: 'Password input')), + SizedBox(width: 250, child: ZetaPhoneInput(label: 'Phone Input')), + SizedBox(width: 250, child: ZetaTimeInput(label: 'Phone Input')), + SizedBox(width: 250, child: ZetaTextInput(label: 'Phone Input')), SizedBox( width: 250, child: ZetaSelectInput( @@ -238,7 +238,7 @@ class _ExamplePageState extends State { onActionButtonPressed: () {}, title: const Text('Screen Header Bar'), ), - const ZetaSearchBar(), + ZetaSearchBar(), ZetaSegmentedControl( segments: const [ ZetaButtonSegment(value: 1, child: Text('Segmented')), diff --git a/lib/src/utils/routes.dart b/lib/src/utils/routes.dart index 8dd7b5e..87138c4 100644 --- a/lib/src/utils/routes.dart +++ b/lib/src/utils/routes.dart @@ -13,7 +13,7 @@ final goRouter = GoRouter( builder: (context, state, navigationShell) { return LayoutBuilder( builder: (context, constraints) { - final showBottomBar = constraints.maxWidth < 479; + final showBottomBar = constraints.maxWidth < 500; final body = CustomScrollView( slivers: [ @@ -42,8 +42,8 @@ final goRouter = GoRouter( onSelect: (value) => navigationShell.goBranch(value), selectedIndex: state.fullPath == '/' ? 0 : 1, items: const [ - ZetaNavigationRailItem(label: 'Welcome', icon: Icon(ZetaIcons.content_round)), - ZetaNavigationRailItem(label: 'Example', icon: Icon(ZetaIcons.star_round)), + ZetaNavigationRailItem(label: 'Welcome', icon: Icon(ZetaIcons.content)), + ZetaNavigationRailItem(label: 'Example', icon: Icon(ZetaIcons.star)), ], ), Expanded(child: body), @@ -54,8 +54,8 @@ final goRouter = GoRouter( onTap: (value) => navigationShell.goBranch(value), currentIndex: state.fullPath == '/' ? 0 : 1, items: const [ - ZetaNavigationBarItem(icon: ZetaIcons.content_round, label: 'Welcome'), - ZetaNavigationBarItem(icon: ZetaIcons.star_round, label: 'Example'), + ZetaNavigationBarItem(icon: ZetaIcons.content, label: 'Welcome'), + ZetaNavigationBarItem(icon: ZetaIcons.star, label: 'Example'), ], ) : null, diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index d53ef64..8e02df2 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true diff --git a/pubspec.yaml b/pubspec.yaml index b4926c7..f6bdefb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,7 +31,7 @@ dependencies: flutter: sdk: flutter go_router: ^14.2.0 - zeta_flutter: ^0.14.0 + zeta_flutter: ^0.15.1 dev_dependencies: flutter_test: diff --git a/release-please/.release-please-manifest.json b/release-please/.release-please-manifest.json new file mode 100644 index 0000000..1332969 --- /dev/null +++ b/release-please/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/release-please/release-please-config.json b/release-please/release-please-config.json new file mode 100644 index 0000000..826f132 --- /dev/null +++ b/release-please/release-please-config.json @@ -0,0 +1,62 @@ +{ + "packages": { + ".": { + "release-type": "dart" + } + }, + "changelog-sections": [ + { + "type": "feat", + "section": "โœจ New Features" + }, + { + "type": "fix", + "section": "๐Ÿชฒ Bug Fixes" + }, + { + "type": "revert", + "section": "๐Ÿ‘€ Reverts" + }, + { + "type": "docs", + "section": "๐Ÿ“ˆ Documentation" + }, + { + "type": "deps", + "section": "โ›“๏ธ Dependencies" + }, + { + "type": "test", + "section": "๐Ÿงช Tests" + }, + { + "type": "chore", + "section": "๐Ÿงน Miscellaneous Chores" + }, + { + "type": "perf", + "section": "Performance Improvements", + "hidden": true + }, + { + "type": "refactor", + "section": "Code Refactoring", + "hidden": true + }, + { + "type": "style", + "section": "Styles", + "hidden": true + }, + { + "type": "build", + "section": "Build System", + "hidden": true + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ] +} \ No newline at end of file diff --git a/test/widget_test.dart b/test/widget_test.dart index 4a97701..826f4f9 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -5,26 +5,110 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:flutter/material.dart'; +import 'dart:ui'; + +import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; import 'package:zeta_flutter_template/main.dart'; void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { + testWidgets('App runs', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + }); + + testWidgets('Bottom navigation bar works on small screen', (WidgetTester tester) async { + // Set the screen size to a small value + tester.view.devicePixelRatio = 1.0; + tester.view.physicalSize = const Size(481, 480); + + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + await tester.pumpAndSettle(); + + // Find the bottom navigation bar widget + final bottomNavigationBarFinder = find.byType(ZetaNavigationBar); + + // Verify that the bottom navigation bar is present + expect(bottomNavigationBarFinder, findsOneWidget); + + // Perform a tap on the first item of the bottom navigation bar + await tester.tap(find.byIcon(ZetaIcons.content_round)); + await tester.pump(); + + // Verify that the first item is selected + expect(bottomNavigationBarFinder, findsOneWidget); + expect(tester.widget(bottomNavigationBarFinder).currentIndex, 0); + + // Perform a tap on the second item of the bottom navigation bar + await tester.tap(find.byIcon(ZetaIcons.star_round)); + await tester.pump(); + + // // Verify that the second item is selected + expect(bottomNavigationBarFinder, findsOneWidget); + expect(tester.widget(bottomNavigationBarFinder).currentIndex, 1); + }); + + testWidgets('Side navigation bar works on large screen', (WidgetTester tester) async { + // Set the screen size to a small value + tester.view.devicePixelRatio = 1.0; + tester.view.physicalSize = const Size(881, 480); + + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Find the bottom navigation bar widget + final navigationRailFinder = find.byType(ZetaNavigationRail); + + // Verify that the bottom navigation bar is present + expect(navigationRailFinder, findsOneWidget); + + // Perform a tap on the first item of the bottom navigation bar + await tester.tap(find.byIcon(ZetaIcons.content)); + await tester.pump(); + + // Verify that the first item is selected + expect(navigationRailFinder, findsOneWidget); + expect(tester.widget(navigationRailFinder).selectedIndex, 0); + + // Perform a tap on the second item of the bottom navigation bar + await tester.tap(find.byIcon(ZetaIcons.star)); + await tester.pump(); + + // // Verify that the second item is selected + expect(navigationRailFinder, findsOneWidget); + expect(tester.widget(navigationRailFinder).selectedIndex, 1); + }); + + testWidgets('Switching between light and dark mode', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(const MyApp()); - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); + // Find the switch widget + final switchFinder = find.byType(ZetaSwitch).first; + + // Verify that the switch is present + // expect(switchFinder, findsOneWidget); + + // Get the current brightness mode + final zetaFinder = find.byType(Zeta); + final initialBrightness = tester.widget(zetaFinder).brightness; + // final brightnessMode = tester.binding.window.platformBrightness; + + // Perform a tap on the switch to toggle the brightness mode + await tester.tap(switchFinder); + await tester.pump(); + + // Verify that the brightness mode has changed + expect(tester.widget(zetaFinder).brightness, isNot(initialBrightness)); - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); + // Perform another tap on the switch to toggle back to the original brightness mode + await tester.tap(switchFinder); await tester.pump(); - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); + // Verify that the brightness mode has changed back to the original mode + expect(tester.widget(zetaFinder).brightness, initialBrightness); }); }