diff --git a/.github/workflows/generate-allure-report.yml b/.github/workflows/generate-allure-report.yml index 9bd73285f97..58bf452e68e 100644 --- a/.github/workflows/generate-allure-report.yml +++ b/.github/workflows/generate-allure-report.yml @@ -67,7 +67,7 @@ jobs: with: earthfile: ./catalyst_voices/ flags: - targets: test-unit + targets: test-report target_flags: runner_address: ${{ secrets.EARTHLY_SATELLITE_ADDRESS }} artifact: "false" diff --git a/Earthfile b/Earthfile index d01f01f6cc1..d348b57094b 100644 --- a/Earthfile +++ b/Earthfile @@ -45,4 +45,14 @@ repo-catalyst-voices-packages: WORKDIR /repo COPY --dir catalyst_voices_packages . + SAVE ARTIFACT /repo repo + +# repo-catalyst-voices-all - Creates artifacts of all configuration files, +# packages and folders related to catalyst_voices frontend. +repo-catalyst-voices-all: + FROM scratch + + WORKDIR /repo + COPY --dir catalyst_voices catalyst_voices_packages utilities melos.yaml pubspec.yaml . + SAVE ARTIFACT /repo repo \ No newline at end of file diff --git a/catalyst_voices/Earthfile b/catalyst_voices/Earthfile index 309bfa50212..5ee37c74a00 100644 --- a/catalyst_voices/Earthfile +++ b/catalyst_voices/Earthfile @@ -8,7 +8,7 @@ VERSION --try --global-cache --arg-scope-and-set 0.7 deps: FROM debian:bookworm-slim RUN apt-get update - RUN apt-get install -y git curl unzip bzip2 bash jq gpg + RUN apt-get install -y git curl unzip bzip2 bash jq gpg lcov COPY --dir test_driver/scripts . RUN chmod +x scripts/install-chrome-linux64.sh && ./scripts/install-chrome-linux64.sh RUN chmod +x scripts/install-edge-linux64.sh && ./scripts/install-edge-linux64.sh @@ -23,7 +23,9 @@ deps: RUN flutter --version RUN flutter doctor -v RUN flutter config --enable-web + RUN dart pub global activate melos RUN dart pub global activate junitreport + RUN dart pub global activate coverage src: FROM +deps @@ -60,6 +62,20 @@ check-flutter-code-generator: # Check diff between local code and earthly artifacts RUN diff /tmp/repo_generated lib/generated/catalyst_gateway +check-static-analysis: + FROM +deps + COPY ../+repo-catalyst-voices-all/repo repo/ + WORKDIR repo + RUN melos bootstrap + RUN melos analyze --fatal-infos --fatal-warnings + +check-code-formatting: + FROM +deps + COPY ../+repo-catalyst-voices-all/repo repo/ + WORKDIR repo + RUN melos bootstrap + RUN melos run format-check + # Build web version of Catalyst Voices build: FROM +src @@ -72,12 +88,12 @@ build: SAVE ARTIFACT web /web AS LOCAL web test-unit: - FROM +build - WORKDIR /frontend - TRY - RUN flutter test --reporter expanded . --machine | tojunit --output flutter.junit-report.xml - FINALLY - SAVE ARTIFACT flutter.junit-report.xml AS LOCAL flutter-unit-tests.junit-report.xml + FROM +deps + COPY ../+repo-catalyst-voices-all/repo repo/ + WORKDIR repo + RUN melos run test-report + WAIT + SAVE ARTIFACT test_reports AS LOCAL test_reports END package: diff --git a/catalyst_voices/lib/pages/coming_soon/coming_soon.dart b/catalyst_voices/lib/pages/coming_soon/coming_soon.dart index 79e7ad0b417..7c4b28710d8 100644 --- a/catalyst_voices/lib/pages/coming_soon/coming_soon.dart +++ b/catalyst_voices/lib/pages/coming_soon/coming_soon.dart @@ -19,8 +19,8 @@ final class ComingSoonPage extends StatelessWidget { decoration: BoxDecoration( image: DecorationImage( image: CatalystImage.asset( - VoicesAssets.images.comingSoonBkg.path, - ).image, + VoicesAssets.images.comingSoonBkg.path, + ).image, fit: BoxFit.cover, ), ), diff --git a/catalyst_voices/packages/catalyst_voices_blocs/test/src/catalyst_voices_blocs_test.dart b/catalyst_voices/packages/catalyst_voices_blocs/test/src/catalyst_voices_blocs_test.dart deleted file mode 100644 index d717b8cb4d7..00000000000 --- a/catalyst_voices/packages/catalyst_voices_blocs/test/src/catalyst_voices_blocs_test.dart +++ /dev/null @@ -1,3 +0,0 @@ -// ignore_for_file: prefer_const_constructors - -void main() {} diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart index e91c8b2ffb1..d3b4a86e54d 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations.dart @@ -4,8 +4,10 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:intl/intl.dart' as intl; -import 'catalyst_voices_localizations_en.dart' deferred as catalyst_voices_localizations_en; -import 'catalyst_voices_localizations_es.dart' deferred as catalyst_voices_localizations_es; +import 'catalyst_voices_localizations_en.dart' + deferred as catalyst_voices_localizations_en; +import 'catalyst_voices_localizations_es.dart' + deferred as catalyst_voices_localizations_es; /// Callers can lookup localized strings with an instance of VoicesLocalizations /// returned by `VoicesLocalizations.of(context)`. @@ -59,7 +61,8 @@ import 'catalyst_voices_localizations_es.dart' deferred as catalyst_voices_local /// be consistent with the languages listed in the VoicesLocalizations.supportedLocales /// property. abstract class VoicesLocalizations { - VoicesLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + VoicesLocalizations(String locale) + : localeName = intl.Intl.canonicalizedLocale(locale.toString()); final String localeName; @@ -67,7 +70,8 @@ abstract class VoicesLocalizations { return Localizations.of(context, VoicesLocalizations); } - static const LocalizationsDelegate delegate = _VoicesLocalizationsDelegate(); + static const LocalizationsDelegate delegate = + _VoicesLocalizationsDelegate(); /// A list of this localizations delegate along with the default localizations /// delegates. @@ -79,7 +83,8 @@ abstract class VoicesLocalizations { /// Additional delegates can be added by appending to this list in /// MaterialApp. This list does not have to be used at all if a custom list /// of delegates is preferred or required. - static const List> localizationsDelegates = >[ + static const List> localizationsDelegates = + >[ delegate, GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, @@ -177,7 +182,8 @@ abstract class VoicesLocalizations { String get comingSoonDescription; } -class _VoicesLocalizationsDelegate extends LocalizationsDelegate { +class _VoicesLocalizationsDelegate + extends LocalizationsDelegate { const _VoicesLocalizationsDelegate(); @override @@ -186,25 +192,27 @@ class _VoicesLocalizationsDelegate extends LocalizationsDelegate ['en', 'es'].contains(locale.languageCode); + bool isSupported(Locale locale) => + ['en', 'es'].contains(locale.languageCode); @override bool shouldReload(_VoicesLocalizationsDelegate old) => false; } Future lookupVoicesLocalizations(Locale locale) { - - // Lookup logic when only language code is specified. switch (locale.languageCode) { - case 'en': return catalyst_voices_localizations_en.loadLibrary().then((dynamic _) => catalyst_voices_localizations_en.VoicesLocalizationsEn()); - case 'es': return catalyst_voices_localizations_es.loadLibrary().then((dynamic _) => catalyst_voices_localizations_es.VoicesLocalizationsEs()); + case 'en': + return catalyst_voices_localizations_en.loadLibrary().then((dynamic _) => + catalyst_voices_localizations_en.VoicesLocalizationsEn()); + case 'es': + return catalyst_voices_localizations_es.loadLibrary().then((dynamic _) => + catalyst_voices_localizations_es.VoicesLocalizationsEs()); } throw FlutterError( - 'VoicesLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' - 'an issue with the localizations generation tool. Please file an issue ' - 'on GitHub with a reproducible sample app and the gen-l10n configuration ' - 'that was used.' - ); + 'VoicesLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' + 'an issue with the localizations generation tool. Please file an issue ' + 'on GitHub with a reproducible sample app and the gen-l10n configuration ' + 'that was used.'); } diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart index 7f270f05dcc..0208ba73b47 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_en.dart @@ -44,5 +44,6 @@ class VoicesLocalizationsEn extends VoicesLocalizations { String get comingSoonTitle2 => 'soon'; @override - String get comingSoonDescription => 'Project Catalyst is the world\'s largest decentralized innovation engine for solving real-world challenges.'; + String get comingSoonDescription => + 'Project Catalyst is the world\'s largest decentralized innovation engine for solving real-world challenges.'; } diff --git a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart index 67c9f0888f1..a8fd058cb60 100644 --- a/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart +++ b/catalyst_voices/packages/catalyst_voices_localization/lib/generated/catalyst_voices_localizations_es.dart @@ -20,7 +20,8 @@ class VoicesLocalizationsEs extends VoicesLocalizations { String get passwordHintText => 'Mi1ContraseñaSecreta'; @override - String get passwordErrorText => 'La contraseña debe tener al menos 8 caracteres'; + String get passwordErrorText => + 'La contraseña debe tener al menos 8 caracteres'; @override String get loginTitleText => 'Acceso'; @@ -44,5 +45,6 @@ class VoicesLocalizationsEs extends VoicesLocalizations { String get comingSoonTitle2 => 'soon'; @override - String get comingSoonDescription => 'Project Catalyst is the world\'s largest decentralized innovation engine for solving real-world challenges.'; + String get comingSoonDescription => + 'Project Catalyst is the world\'s largest decentralized innovation engine for solving real-world challenges.'; } diff --git a/catalyst_voices/packages/catalyst_voices_models/test/src/catalyst_voices_models_test.dart b/catalyst_voices/packages/catalyst_voices_models/test/src/catalyst_voices_models_test.dart deleted file mode 100644 index ab73b3a234a..00000000000 --- a/catalyst_voices/packages/catalyst_voices_models/test/src/catalyst_voices_models_test.dart +++ /dev/null @@ -1 +0,0 @@ -void main() {} diff --git a/catalyst_voices/packages/catalyst_voices_repositories/lib/src/catalyst_data_gateway_repository.dart b/catalyst_voices/packages/catalyst_voices_repositories/lib/src/catalyst_data_gateway_repository.dart index 083c0ba800c..394d7989131 100644 --- a/catalyst_voices/packages/catalyst_voices_repositories/lib/src/catalyst_data_gateway_repository.dart +++ b/catalyst_voices/packages/catalyst_voices_repositories/lib/src/catalyst_data_gateway_repository.dart @@ -1,7 +1,8 @@ import 'dart:async'; import 'package:catalyst_voices_models/catalyst_voices_models.dart'; -import 'package:catalyst_voices_services/generated/catalyst_gateway/cat_gateway_api.enums.swagger.dart' as enums; +import 'package:catalyst_voices_services/generated/catalyst_gateway/cat_gateway_api.enums.swagger.dart' + as enums; import 'package:catalyst_voices_services/generated/catalyst_gateway/cat_gateway_api.swagger.dart'; import 'package:chopper/chopper.dart'; import 'package:result_type/result_type.dart'; @@ -15,9 +16,9 @@ import 'package:result_type/result_type.dart'; // The repository uses, under the hood, the [CatGatewayApi] directly generated // from backend OpenAPI specification. // -// To use the repository is necessary to initialize it by specifying the API +// To use the repository is necessary to initialize it by specifying the API // base URL: -// +// // ```dart // final repository = CatalystDataGatewayRepository(Uri.parse('https://example.org/api')); // ``` @@ -28,7 +29,7 @@ import 'package:result_type/result_type.dart'; // ```dart // final health_status = await repository.getHealthLive(); // ``` -// +// // fetch staked ADA by stake address: // // ```dart @@ -48,11 +49,10 @@ final class CatalystDataGatewayRepository { final CatGatewayApi _catGatewayApi; CatalystDataGatewayRepository( - Uri baseUrl, - {CatGatewayApi? catGatewayApiInstance,} - ) - : _catGatewayApi = catGatewayApiInstance ?? - CatGatewayApi.create(baseUrl: baseUrl); + Uri baseUrl, { + CatGatewayApi? catGatewayApiInstance, + }) : _catGatewayApi = + catGatewayApiInstance ?? CatGatewayApi.create(baseUrl: baseUrl); Future> getHealthStarted() async { try { @@ -120,10 +120,10 @@ final class CatalystDataGatewayRepository { Result _emptyBodyOrThrow(Response response) { // `bodyOrThrow` from chopper can't be used when the body is empty (like in // case the endpoint replies with 204) because it would throw an exception - // as a false positive. + // as a false positive. if (response.isSuccessful) { return Success(null); } throw ChopperHttpException(response); - } + } } diff --git a/catalyst_voices/packages/catalyst_voices_repositories/test/src/catalyst_data_gateway_repository/catalyst_data_gateway_repository_test.dart b/catalyst_voices/packages/catalyst_voices_repositories/test/src/catalyst_data_gateway_repository/catalyst_data_gateway_repository_test.dart index 95cf84e714b..746020be8f8 100644 --- a/catalyst_voices/packages/catalyst_voices_repositories/test/src/catalyst_data_gateway_repository/catalyst_data_gateway_repository_test.dart +++ b/catalyst_voices/packages/catalyst_voices_repositories/test/src/catalyst_data_gateway_repository/catalyst_data_gateway_repository_test.dart @@ -214,10 +214,12 @@ void main() { }); test('getCardanoSyncState success', () async { + const blockHash = + '0x0000000000000000000000000000000000000000000000000000000000000000'; + final syncState = SyncState( slotNumber: 5, - blockHash: - '0x0000000000000000000000000000000000000000000000000000000000000000', + blockHash: blockHash, lastUpdated: DateTime.utc(1970), ); final repository = setupRepository( diff --git a/catalyst_voices/packages/catalyst_voices_services/test/src/catalyst_voices_services_test.dart b/catalyst_voices/packages/catalyst_voices_services/test/src/catalyst_voices_services_test.dart deleted file mode 100644 index ab73b3a234a..00000000000 --- a/catalyst_voices/packages/catalyst_voices_services/test/src/catalyst_voices_services_test.dart +++ /dev/null @@ -1 +0,0 @@ -void main() {} diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/io_platform.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/io_platform.dart index 5b3db720fea..6377e4512a9 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/io_platform.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/io_platform.dart @@ -27,16 +27,16 @@ final class CatalystPlatform { static bool get isWindows => Platform.isWindows; static Map get identifiers => { - PlatformKey.android: isAndroid, - PlatformKey.desktop: isDesktop, - PlatformKey.fuchsia: isFuchsia, - PlatformKey.iOS: isIOS, - PlatformKey.linux: isLinux, - PlatformKey.macOS: isMacOS, - PlatformKey.mobile: isMobile, - PlatformKey.mobileWeb: isMobileWeb, - PlatformKey.web: isWeb, - PlatformKey.webDesktop: isWebDesktop, - PlatformKey.windows: isWindows, - }; + PlatformKey.android: isAndroid, + PlatformKey.desktop: isDesktop, + PlatformKey.fuchsia: isFuchsia, + PlatformKey.iOS: isIOS, + PlatformKey.linux: isLinux, + PlatformKey.macOS: isMacOS, + PlatformKey.mobile: isMobile, + PlatformKey.mobileWeb: isMobileWeb, + PlatformKey.web: isWeb, + PlatformKey.webDesktop: isWebDesktop, + PlatformKey.windows: isWindows, + }; } diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/web_platform.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/web_platform.dart index a7a9d074d79..e9e4c62e7c4 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/web_platform.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform/web_platform.dart @@ -34,20 +34,20 @@ final class CatalystPlatform { ]; return mobileIdentifiers.any(userAgent.contains); } - + static Map get identifiers => { - PlatformKey.android: isAndroid, - PlatformKey.desktop: isDesktop, - PlatformKey.fuchsia: isFuchsia, - PlatformKey.iOS: isIOS, - PlatformKey.linux: isLinux, - PlatformKey.macOS: isMacOS, - PlatformKey.mobile: isMobile, - PlatformKey.mobileWeb: isMobileWeb, - PlatformKey.web: isWeb, - PlatformKey.webDesktop: isWebDesktop, - PlatformKey.windows: isWindows, - }; + PlatformKey.android: isAndroid, + PlatformKey.desktop: isDesktop, + PlatformKey.fuchsia: isFuchsia, + PlatformKey.iOS: isIOS, + PlatformKey.linux: isLinux, + PlatformKey.macOS: isMacOS, + PlatformKey.mobile: isMobile, + PlatformKey.mobileWeb: isMobileWeb, + PlatformKey.web: isWeb, + PlatformKey.webDesktop: isWebDesktop, + PlatformKey.windows: isWindows, + }; const CatalystPlatform._(); } diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform_aware_builder/platform_aware_builder.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform_aware_builder/platform_aware_builder.dart index 8a444265191..cfcf9266eff 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform_aware_builder/platform_aware_builder.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/platform_aware_builder/platform_aware_builder.dart @@ -2,21 +2,21 @@ import 'package:catalyst_voices_shared/src/platform/catalyst_platform.dart'; import 'package:catalyst_voices_shared/src/platform/platform_key.dart'; import 'package:flutter/widgets.dart'; -// A [PlatformAwareBuilder] is a StatelessWidget that is aware of the current +// A [PlatformAwareBuilder] is a StatelessWidget that is aware of the current // platform. // // This is an abstract widget that has a required argument [builder] that can -// consume platform-specific data automatically based on platform that is +// consume platform-specific data automatically based on platform that is // detected. // // The platform detection happens in [CatalystPlatform]. // -// The widget accepts an argument for each specific platform defined in +// The widget accepts an argument for each specific platform defined in // [PlatformKey]. The platform specific [data] is selected when two conditions // are verified at the same time: // - the platform is detected // - the platform-specific argument is present -// In case those conditions are not verified the [other] argument is used (and +// In case those conditions are not verified the [other] argument is used (and // because of this it is required). // The type of the platform specific data is generic. // @@ -63,19 +63,19 @@ class PlatformAwareBuilder extends StatelessWidget { T? windows, required T other, }) : _platformData = { - PlatformKey.android: android, - PlatformKey.desktop: desktop, - PlatformKey.fuchsia: fuchsia, - PlatformKey.iOS: iOS, - PlatformKey.linux: linux, - PlatformKey.macOS: macOS, - PlatformKey.mobile: mobile, - PlatformKey.mobileWeb: mobileWeb, - PlatformKey.web: web, - PlatformKey.webDesktop: webDesktop, - PlatformKey.windows: windows, - PlatformKey.other: other, - }; + PlatformKey.android: android, + PlatformKey.desktop: desktop, + PlatformKey.fuchsia: fuchsia, + PlatformKey.iOS: iOS, + PlatformKey.linux: linux, + PlatformKey.macOS: macOS, + PlatformKey.mobile: mobile, + PlatformKey.mobileWeb: mobileWeb, + PlatformKey.web: web, + PlatformKey.webDesktop: webDesktop, + PlatformKey.windows: windows, + PlatformKey.other: other, + }; @override Widget build(BuildContext context) { @@ -84,13 +84,13 @@ class PlatformAwareBuilder extends StatelessWidget { T _getPlatformData() { final currentPlatformKey = CatalystPlatform.identifiers.entries - .firstWhere( - // We select the platform only if the platform-specific data - // is also present. - (entry) => entry.value && (_platformData[entry.key] != null), - orElse: () => const MapEntry(PlatformKey.other, true), - ) - .key; + .firstWhere( + // We select the platform only if the platform-specific data + // is also present. + (entry) => entry.value && (_platformData[entry.key] != null), + orElse: () => const MapEntry(PlatformKey.other, true), + ) + .key; return _platformData[currentPlatformKey]!; } } diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart index aec88b14208..55da2f90dca 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart @@ -1,17 +1,17 @@ import 'package:catalyst_voices_shared/src/responsive/responsive_breakpoint_key.dart'; import 'package:flutter/widgets.dart'; -// A [ResponsiveBuilder] is a StatelessWidget that is aware about the current +// A [ResponsiveBuilder] is a StatelessWidget that is aware about the current // device breakpoint. // // This is an abstract widget that has a required argument [builder] that can -// consume breakpoint-specific data automatically based on breakpoint that is +// consume breakpoint-specific data automatically based on breakpoint that is // detected. // -// The breakpoint is identified by using the screen width exposed by MediaQuery +// The breakpoint is identified by using the screen width exposed by MediaQuery // of the context. // -// The widget accepts an argument for each breakpoint defined in +// The widget accepts an argument for each breakpoint defined in // [ResponsiveBreakpointKey]. The breakpoint specific [data] is selected when: // - the breakpoint is detected // - the breakpoint-specific data argument is present @@ -32,7 +32,7 @@ import 'package:flutter/widgets.dart'; // ); // // or to have a specific padding: -// +// // ```dart // ResponsiveBuilder( // xs: EdgeInsets.all(4.0), @@ -57,12 +57,12 @@ class ResponsiveBuilder extends StatelessWidget { T? lg, required T other, }) : _responsiveData = { - ResponsiveBreakpointKey.xs: xs, - ResponsiveBreakpointKey.sm: sm, - ResponsiveBreakpointKey.md: md, - ResponsiveBreakpointKey.lg: lg, - ResponsiveBreakpointKey.other: other, - }; + ResponsiveBreakpointKey.xs: xs, + ResponsiveBreakpointKey.sm: sm, + ResponsiveBreakpointKey.md: md, + ResponsiveBreakpointKey.lg: lg, + ResponsiveBreakpointKey.other: other, + }; @override Widget build(BuildContext context) { @@ -73,18 +73,17 @@ class ResponsiveBuilder extends StatelessWidget { final screenWidth = MediaQuery.sizeOf(context).width; final breakpointKey = _breakpoints.entries - .firstWhere( - (entry) => ( - screenWidth >= entry.value.min && - screenWidth <= entry.value.max && - _responsiveData[entry.key] != null - ), - orElse: () => const MapEntry( - ResponsiveBreakpointKey.other, (min: 0, max: 0), - ), - ) - .key; - return _responsiveData[breakpointKey]!; + .firstWhere( + (entry) => (screenWidth >= entry.value.min && + screenWidth <= entry.value.max && + _responsiveData[entry.key] != null), + orElse: () => const MapEntry( + ResponsiveBreakpointKey.other, + (min: 0, max: 0), + ), + ) + .key; + return _responsiveData[breakpointKey]!; } final Map _breakpoints = { diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart index c7330ce7ae2..ec07aa2fb5e 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart @@ -2,17 +2,17 @@ import 'package:catalyst_voices_shared/src/responsive/responsive_breakpoint_key. import 'package:catalyst_voices_shared/src/responsive/responsive_builder.dart'; import 'package:flutter/material.dart'; -// A [ResponsiveChild] is a StatelessWidget that selects a WidgetBuilder based +// A [ResponsiveChild] is a StatelessWidget that selects a WidgetBuilder based // on the current screen size and execute it. // This is a simple wrapper around ResponsiveBuilder to simplify development and // make it explicit for a reader. // -// The possible arguments are [xs], [sm], [md], [lg], [other] following the +// The possible arguments are [xs], [sm], [md], [lg], [other] following the // the ResponsiveBuilder arguments. // [other] is required and acts as fallback. // // Example usage: -// +// // ```dart // ResponsiveChild( // xs: (context) => const Text('Simple text for extra small screens.'), @@ -43,12 +43,12 @@ class ResponsiveChild extends StatelessWidget { WidgetBuilder? lg, required WidgetBuilder other, }) : _widgets = { - ResponsiveBreakpointKey.xs: xs, - ResponsiveBreakpointKey.sm: sm, - ResponsiveBreakpointKey.md: md, - ResponsiveBreakpointKey.lg: lg, - ResponsiveBreakpointKey.other: other, - }; + ResponsiveBreakpointKey.xs: xs, + ResponsiveBreakpointKey.sm: sm, + ResponsiveBreakpointKey.md: md, + ResponsiveBreakpointKey.lg: lg, + ResponsiveBreakpointKey.other: other, + }; @override Widget build(BuildContext context) { diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart index 2007d50299b..a19087b5b1a 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart @@ -5,16 +5,16 @@ import 'package:flutter/widgets.dart'; // A [ResponsivePadding] is a StatelessWidget that applies a padding based on // the current screen size. // -// The widget wraps its [child] in a ResponsiveBuilder that calculates the +// The widget wraps its [child] in a ResponsiveBuilder that calculates the // proper padding value based on the screen size and wraps it again in a Padding // to display the selected padding value. // -// The possible arguments are [xs], [sm], [md], [lg], [other] following the +// The possible arguments are [xs], [sm], [md], [lg], [other] following the // Material design standards and the ResponsiveBuilder arguments. // Each screen size has a default value to simplify widget usage. // // Example usage: -// +// // ```dart // ResponsivePadding( // xs: const EdgeInsets.all(4.0), @@ -38,12 +38,12 @@ class ResponsivePadding extends StatelessWidget { EdgeInsets lg = const EdgeInsets.all(16), EdgeInsets other = const EdgeInsets.all(8), }) : _paddings = { - ResponsiveBreakpointKey.xs: xs, - ResponsiveBreakpointKey.sm: sm, - ResponsiveBreakpointKey.md: md, - ResponsiveBreakpointKey.lg: lg, - ResponsiveBreakpointKey.other: other, - }; + ResponsiveBreakpointKey.xs: xs, + ResponsiveBreakpointKey.sm: sm, + ResponsiveBreakpointKey.md: md, + ResponsiveBreakpointKey.lg: lg, + ResponsiveBreakpointKey.other: other, + }; @override Widget build(BuildContext context) { @@ -59,5 +59,4 @@ class ResponsivePadding extends StatelessWidget { other: _paddings[ResponsiveBreakpointKey.other]!, ); } - } diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart index 0cec3272b27..cc020619ab1 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart @@ -3,15 +3,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - Widget buildApp() => MaterialApp( - home: Scaffold( - body: PlatformAwareBuilder( - other: 'other', - builder: (context, platformData) => Text(platformData!), - ), - ), - ); + home: Scaffold( + body: PlatformAwareBuilder( + other: 'other', + builder: (context, platformData) => Text(platformData!), + ), + ), + ); group('Test platform detection', () { testWidgets('PlatformWidgetBuilder fallbacks to other', (tester) async { @@ -20,7 +19,6 @@ void main() { expect(find.byType(Text), findsOneWidget); // Check the output contains the platform that was tested. expect(find.text('other'), findsOneWidget); - }); }); } diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart index f786cd82b94..a3d1cb13f81 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart @@ -6,14 +6,15 @@ void main() { Widget buildApp( Size size, Widget child, - ) => MediaQuery( - data: MediaQueryData(size: size), - child: MaterialApp( - home: Scaffold( - body: child, - ), - ), - ); + ) => + MediaQuery( + data: MediaQueryData(size: size), + child: MaterialApp( + home: Scaffold( + body: child, + ), + ), + ); group('Test screen sizes with Text child', () { final sizesToTest = { @@ -25,77 +26,73 @@ void main() { }; for (final entry in sizesToTest.entries) { - testWidgets( - 'ResponsiveBuilder adapts to screen of width $entry.key', - (tester) async { - await tester.pumpWidget( - buildApp( - Size.fromWidth(entry.key), - ResponsiveBuilder( - xs: 'Xs device', - sm: 'Small device', - md: 'Medium device', - lg: 'Large device', - other: 'Other device', - builder: (context, data) => Text(data!), - ), + testWidgets('ResponsiveBuilder adapts to screen of width $entry.key', + (tester) async { + await tester.pumpWidget( + buildApp( + Size.fromWidth(entry.key), + ResponsiveBuilder( + xs: 'Xs device', + sm: 'Small device', + md: 'Medium device', + lg: 'Large device', + other: 'Other device', + builder: (context, data) => Text(data!), ), - ); + ), + ); - final testedElement = find.byType(Text); - // Verify the Widget renders properly - expect(testedElement, findsOneWidget); - // Verify the proper text is rendered - expect(find.text(entry.value), findsOneWidget); - } - ); + final testedElement = find.byType(Text); + // Verify the Widget renders properly + expect(testedElement, findsOneWidget); + // Verify the proper text is rendered + expect(find.text(entry.value), findsOneWidget); + }); } }); group('Test screen sizes with specific Padding', () { final sizesToTest = { 280.0: const EdgeInsets.all(2), - 620.0: const EdgeInsets.all(4), + 620.0: const EdgeInsets.all(4), 1280.0: const EdgeInsets.all(8), 1600.0: const EdgeInsets.all(16), 3000.0: const EdgeInsets.all(32), }; for (final entry in sizesToTest.entries) { - testWidgets( - 'ResponsiveBuilder adapts to screen of width $entry.key', - (tester) async { - await tester.pumpWidget( - buildApp( - Size.fromWidth(entry.key), - ResponsiveBuilder( - xs: const EdgeInsets.all(2), - sm: const EdgeInsets.all(4), - md: const EdgeInsets.all(8), - lg: const EdgeInsets.all(16), - other: const EdgeInsets.all(32), - builder: (context, padding) => Padding( - padding: padding!, - child: const Text('Test'), - ), + testWidgets('ResponsiveBuilder adapts to screen of width $entry.key', + (tester) async { + await tester.pumpWidget( + buildApp( + Size.fromWidth(entry.key), + ResponsiveBuilder( + xs: const EdgeInsets.all(2), + sm: const EdgeInsets.all(4), + md: const EdgeInsets.all(8), + lg: const EdgeInsets.all(16), + other: const EdgeInsets.all(32), + builder: (context, padding) => Padding( + padding: padding!, + child: const Text('Test'), ), ), - ); + ), + ); - final testedElement = find.byType(Text); - // Verify the Widget renders properly - expect(testedElement, findsOneWidget); + final testedElement = find.byType(Text); + // Verify the Widget renders properly + expect(testedElement, findsOneWidget); - final paddingWidget = tester.widget( - find.ancestor( - of: testedElement, - matching: find.byType(Padding), - ), - ); - // Check that the padding corresponds - expect(paddingWidget.padding, entry.value); - } - ); + final paddingWidget = tester.widget( + find.ancestor( + of: testedElement, + matching: find.byType(Padding), + ), + ); + // Check that the padding corresponds + expect(paddingWidget.padding, entry.value); + }); } }); } diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart index eeb1cc5f5bf..0658fd898fd 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart @@ -4,89 +4,82 @@ import 'package:flutter_test/flutter_test.dart'; void main() { Widget buildApp(Size size) => MediaQuery( - data: MediaQueryData(size: size), - child: MaterialApp( - home: Scaffold( - body: ResponsiveChild( - xs: (context) => const Text('Simple text for extra small screens.'), - sm: (context) => const Padding( - padding: EdgeInsets.all(50), - child: Text('Text with padding for small screens.'), + data: MediaQueryData(size: size), + child: MaterialApp( + home: Scaffold( + body: ResponsiveChild( + xs: (context) => + const Text('Simple text for extra small screens.'), + sm: (context) => const Padding( + padding: EdgeInsets.all(50), + child: Text('Text with padding for small screens.'), + ), + md: (context) => const Column( + children: [ + Text('This is'), + Text('a set'), + Text('of Texts'), + Text('for medium screens.'), + ], + ), + other: (context) => const Text('The fallback widget.'), + ), ), - md: (context) => const Column( - children: [ - Text('This is'), - Text('a set'), - Text('of Texts'), - Text('for medium screens.'), - ], - ), - other: (context) => const Text('The fallback widget.'), ), - ), - ), - ); + ); group('Test screen sizes', () { - testWidgets( - 'ResponsiveChild outputs a text for extra-small screens', - (tester) async { - await tester.pumpWidget( - buildApp(const Size.fromWidth(280)), - ); - final testedElement = find.byType(Text); - expect(testedElement, findsOneWidget); - expect( - find.text('Simple text for extra small screens.'), - findsOneWidget, - ); - } - ); - testWidgets( - 'ResponsiveChild outputs a text with padding for small screens', - (tester) async { - await tester.pumpWidget( - buildApp(const Size.fromWidth(620)), - ); - final testedElement = find.byType(Text); - expect(testedElement, findsOneWidget); - expect( - find.text('Text with padding for small screens.'), - findsOneWidget, - ); - final paddingWidget = tester.widget( - find.ancestor( - of: testedElement, - matching: find.byType(Padding), - ), - ); - expect(paddingWidget.padding, const EdgeInsets.all(50)); - } - ); - testWidgets( - 'ResponsiveChild outputs four texts for medium screens', - (tester) async { - await tester.pumpWidget( - buildApp(const Size.fromWidth(1280)), - ); - final testedElements = find.byType(Text); - expect(testedElements, findsExactly(4)); - expect(find.text('This is'), findsOneWidget); - expect(find.text('a set'), findsOneWidget); - expect(find.text('of Texts'), findsOneWidget); - expect(find.text('for medium screens.'), findsOneWidget); - } - ); - testWidgets( - 'ResponsiveChild fallback to other for large screens', - (tester) async { - await tester.pumpWidget( - buildApp(const Size.fromWidth(1600)), - ); - final testedElements = find.byType(Text); - expect(testedElements, findsOneWidget); - expect(find.text('The fallback widget.'), findsOneWidget); - } - ); + testWidgets('ResponsiveChild outputs a text for extra-small screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(280)), + ); + final testedElement = find.byType(Text); + expect(testedElement, findsOneWidget); + expect( + find.text('Simple text for extra small screens.'), + findsOneWidget, + ); + }); + testWidgets('ResponsiveChild outputs a text with padding for small screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(620)), + ); + final testedElement = find.byType(Text); + expect(testedElement, findsOneWidget); + expect( + find.text('Text with padding for small screens.'), + findsOneWidget, + ); + final paddingWidget = tester.widget( + find.ancestor( + of: testedElement, + matching: find.byType(Padding), + ), + ); + expect(paddingWidget.padding, const EdgeInsets.all(50)); + }); + testWidgets('ResponsiveChild outputs four texts for medium screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(1280)), + ); + final testedElements = find.byType(Text); + expect(testedElements, findsExactly(4)); + expect(find.text('This is'), findsOneWidget); + expect(find.text('a set'), findsOneWidget); + expect(find.text('of Texts'), findsOneWidget); + expect(find.text('for medium screens.'), findsOneWidget); + }); + testWidgets('ResponsiveChild fallback to other for large screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(1600)), + ); + final testedElements = find.byType(Text); + expect(testedElements, findsOneWidget); + expect(find.text('The fallback widget.'), findsOneWidget); + }); }); } diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_padding_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_padding_test.dart index 972173b8246..18c88bd25ed 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_padding_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_padding_test.dart @@ -3,23 +3,21 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - Widget buildApp(Size size) => MediaQuery( - data: MediaQueryData(size: size), - child: MaterialApp( - home: Scaffold( - body: ResponsivePadding( - xs: const EdgeInsets.all(2), - sm: const EdgeInsets.symmetric(vertical: 3), - md: const EdgeInsets.symmetric(horizontal: 4), - lg: const EdgeInsets.only(top: 5), - child: const Text('Test data!'), + data: MediaQueryData(size: size), + child: MaterialApp( + home: Scaffold( + body: ResponsivePadding( + xs: const EdgeInsets.all(2), + sm: const EdgeInsets.symmetric(vertical: 3), + md: const EdgeInsets.symmetric(horizontal: 4), + lg: const EdgeInsets.only(top: 5), + child: const Text('Test data!'), + ), + ), ), - ), - ), - ); + ); group('Test screen sizes', () { - final sizesToTest = { 280.0: const EdgeInsets.all(2), 620.0: const EdgeInsets.symmetric(vertical: 3), @@ -28,27 +26,24 @@ void main() { }; for (final entry in sizesToTest.entries) { - testWidgets( - 'ResponsivePadding adapts to screen of width $entry.key', - (tester) async { - await tester.pumpWidget( - buildApp(Size.fromWidth(entry.key)), - ); + testWidgets('ResponsivePadding adapts to screen of width $entry.key', + (tester) async { + await tester.pumpWidget( + buildApp(Size.fromWidth(entry.key)), + ); - final testedElement = find.byType(Text); - // Verify the Widget renders properly - expect(testedElement, findsOneWidget); - final paddingWidget = tester.widget( - find.ancestor( - of: testedElement, - matching: find.byType(Padding), - ), - ); - // Check that the padding corresponds - expect(paddingWidget.padding, entry.value); - } - ); + final testedElement = find.byType(Text); + // Verify the Widget renders properly + expect(testedElement, findsOneWidget); + final paddingWidget = tester.widget( + find.ancestor( + of: testedElement, + matching: find.byType(Padding), + ), + ); + // Check that the padding corresponds + expect(paddingWidget.padding, entry.value); + }); } - }); } diff --git a/catalyst_voices/packages/catalyst_voices_view_models/test/src/catalyst_voices_view_models_test.dart b/catalyst_voices/packages/catalyst_voices_view_models/test/src/catalyst_voices_view_models_test.dart deleted file mode 100644 index b0d5ab372b4..00000000000 --- a/catalyst_voices/packages/catalyst_voices_view_models/test/src/catalyst_voices_view_models_test.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:test/test.dart'; - -void main() { - group('CatalystVoicesViewModels', () {}); -} diff --git a/catalyst_voices/test/app/view/app_test.dart b/catalyst_voices/test/app/view/app_test.dart index ab73b3a234a..28bfe199c9d 100644 --- a/catalyst_voices/test/app/view/app_test.dart +++ b/catalyst_voices/test/app/view/app_test.dart @@ -1 +1,11 @@ -void main() {} +import 'package:catalyst_voices/pages/coming_soon/coming_soon.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../helpers/helpers.dart'; + +void main() { + testWidgets('placeholder_test', (tester) async { + await tester.pumpApp(const ComingSoonPage()); + await tester.pumpAndSettle(); + }); +} diff --git a/melos.yaml b/melos.yaml index ca213ddd4f9..8d7cfb2b61c 100644 --- a/melos.yaml +++ b/melos.yaml @@ -2,7 +2,7 @@ name: catalyst_voices repository: https://github.com/input-output-hk/catalyst-voices packages: - - catalyst_voices/* + - catalyst_voices - catalyst_voices/packages/** - catalyst_voices_packages/** - utilities/* @@ -13,7 +13,7 @@ command: workspaceChangelog: true bootstrap: environment: - sdk: '>=3.3.0 <4.0.0' + sdk: ">=3.3.0 <4.0.0" flutter: 3.19.5 dependencies: bloc_concurrency: ^0.2.2 @@ -29,52 +29,61 @@ command: mocktail: ^1.0.1 scripts: - lint: - run: melos run analyze - description: Run all static analysis checks. - - format: - run: melos exec dart format . --fix - description: Run `dart format` for all packages. - - format-check: - run: melos exec dart format . --set-exit-if-changed - description: Run `dart format` checks for all packages. - - analyze: - # We are setting the concurrency to 1 because a higher concurrency can crash - # the analysis server on low performance machines (like GitHub Actions). - run: | - melos exec -c 1 -- \ - dart analyze . --fatal-infos - description: | - Run `dart analyze` in all packages. - - Note: you can also rely on your IDEs Dart Analysis / Issues window. - metrics: run: | - melos exec -c 1 --ignore="*example*" -- \ + melos exec -c 1 -- \ flutter pub run dart_code_metrics:metrics analyze description: | Run `dart_code_metrics` in all packages. - Note: you can also rely on your IDEs Dart Analysis / Issues window. + format: + run: | + melos exec -c 1 --dir-exists="lib" -- dart format lib --fix + melos exec -c 1 --dir-exists="test" -- dart format test --fix + melos exec -c 1 --dir-exists="integration_test" -- dart format integration_test --fix + description: Run `dart format` for all packages. + + format-check: + run: | + melos exec -c 1 --dir-exists="lib" -- dart format lib --set-exit-if-changed + melos exec -c 1 --dir-exists="test" -- dart format test --set-exit-if-changed + melos exec -c 1 --dir-exists="integration_test" -- dart format integration_test --set-exit-if-changed + description: Run `dart format` checks for all packages. + test:select: - run: melos exec -- flutter test + run: | + melos exec -c 1 --dir-exists="test" -- flutter test description: Run `flutter test` for selected packages. test: - run: melos run test:select --no-select - description: Run all Flutter tests in this project. + run: | + melos run test:select --no-select + description: Run `flutter test` for all packages. - coverage: + test-report: run: | - melos exec -- flutter test --coverage && - melos exec -- genhtml coverage/lcov.info --output-directory=coverage/ - description: Generate coverage for the selected package. + # cleanup from previous build and create new folders + rm -fR $MELOS_ROOT_PATH/test_reports + mkdir $MELOS_ROOT_PATH/test_reports + + # run tests, generate junit reports in /test_reports/ & code coverage report + melos exec -c 1 --dir-exists="test" -- \ + "flutter test --reporter expanded --coverage --machine | tojunit --output MELOS_ROOT_PATH/test_reports/MELOS_PACKAGE_NAME.junit-report.xml" - build:pub_get:all: - run: flutter pub get - exec: - concurrency: 6 - description: Install all dependencies \ No newline at end of file + # removes code coverage for generated code + melos exec -c 1 --dir-exists="test" -- \ + lcov --remove coverage/lcov.info -o coverage/lcov.info --ignore-errors unused,unused \ + '*.swagger.dart' \ + '*.chopper.dart' \ + '*.g.dart' \ + '*.freezed.dart' \ + 'lib/generated/**' + + # converts coverage to a HTML report + melos exec -c 1 --dir-exists="test" -- \ + "genhtml coverage/lcov.info --output-directory=coverage/" + description: | + Run `flutter test` for all packages and generate junit and coverage reports. + The test reports are saved in /test_reports folder. + The coverages are saved for each package separately in /coverage folder. diff --git a/utilities/catalyst_voices_remote_widgets/test/src/catalyst_voices_remote_widgets_test.dart b/utilities/catalyst_voices_remote_widgets/test/src/catalyst_voices_remote_widgets_test.dart deleted file mode 100644 index ab73b3a234a..00000000000 --- a/utilities/catalyst_voices_remote_widgets/test/src/catalyst_voices_remote_widgets_test.dart +++ /dev/null @@ -1 +0,0 @@ -void main() {}