diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cba2ba..44eb589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ 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). +## [1.5.0] + +### Added +- **EngineTrackingInitialize**: Central initializer for analytics and bug tracking services +- **Nullable Parameters**: Optional initialization of analytics or bug tracking individually +- **Dartdoc Documentation**: Complete public API documentation for all methods and parameters + +### Enhanced +- **Flexible Initialization**: Initialize both services, only analytics, or only bug tracking +- **Parallel Execution**: Optimized Future.wait for maximum performance +- **Test Coverage**: 17 new tests for centralized initialization scenarios + ## [1.4.1] ### Enhanced diff --git a/README.md b/README.md index aa1417e..641c544 100644 --- a/README.md +++ b/README.md @@ -282,7 +282,49 @@ cd example && flutter run - **🌐 Exemplo HTTP Tracking**: Requisições com PokéAPI e JSONPlaceholder - **👁️ Exemplo View Tracking**: Sistema automático de tracking de telas -### 🎯 Configuração Básica +### 🚀 Inicialização Centralizada (Recomendado) + +**Novo!** Use o `EngineTrackingInitialize` para inicializar Analytics e Bug Tracking de uma só vez: + +```dart +import 'package:engine_tracking/engine_tracking.dart'; + +// Ambos os serviços +await EngineTrackingInitialize.initWithModels( + analyticsModel: EngineAnalyticsModel(/* configs */), + bugTrackingModel: EngineBugTrackingModel(/* configs */), +); + +// Apenas Analytics +await EngineTrackingInitialize.initWithModels( + analyticsModel: EngineAnalyticsModel(/* configs */), + bugTrackingModel: null, +); + +// Apenas Bug Tracking +await EngineTrackingInitialize.initWithModels( + analyticsModel: null, + bugTrackingModel: EngineBugTrackingModel(/* configs */), +); + +// Com Adapters (controle granular) +await EngineTrackingInitialize.initWithAdapters( + analyticsAdapters: [EngineFirebaseAnalyticsAdapter(/* config */)], + bugTrackingAdapters: null, // Skip bug tracking +); + +// Inicialização rápida (ambos desabilitados) +await EngineTrackingInitialize.initWithDefaults(); + +// Status +bool bothReady = EngineTrackingInitialize.isInitialized; +bool anyEnabled = EngineTrackingInitialize.isEnabled; + +// Cleanup +await EngineTrackingInitialize.dispose(); +``` + +### 🎯 Configuração Básica (Método Individual) ```dart import 'package:engine_tracking/engine_tracking.dart'; @@ -335,8 +377,8 @@ Future setupTracking() async { googleLoggingConfig: const EngineGoogleLoggingConfig(enabled: true, /* configs */), ); - await EngineAnalytics.init(analyticsModel); - await EngineBugTracking.init(bugTrackingModel); + await EngineAnalytics.initWithModel(analyticsModel); + await EngineBugTracking.initWithModel(bugTrackingModel); } ``` diff --git a/analysis_options.yaml b/analysis_options.yaml index 2b2fbf4..a09a058 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,7 +1,3 @@ -# Flutter/Dart 2025 - Comprehensive Lint Configuration -# Based on flutter_lints 6.0.0 and modern best practices -# Consulte este arquivo como referência para nosso padrão de lint - include: package:flutter_lints/flutter.yaml formatter: diff --git a/lib/src/engine_tracking_initialize.dart b/lib/src/engine_tracking_initialize.dart new file mode 100644 index 0000000..6fe253d --- /dev/null +++ b/lib/src/engine_tracking_initialize.dart @@ -0,0 +1,81 @@ +import 'dart:async'; + +import 'package:engine_tracking/engine_tracking.dart'; + +/// Central initializer for Engine Tracking services +/// +/// Provides methods to initialize analytics and bug tracking services +/// together or individually with adapters, models, or default configurations. +class EngineTrackingInitialize { + EngineTrackingInitialize._(); + + /// Initialize tracking services with custom adapters + /// + /// [analyticsAdapters] List of analytics adapters to initialize. + /// Can be null to skip analytics initialization. + /// + /// [bugTrackingAdapters] List of bug tracking adapters to initialize. + /// Can be null to skip bug tracking initialization. + static Future initWithAdapters({ + final List? analyticsAdapters, + final List? bugTrackingAdapters, + }) async { + final futures = >[]; + + if (analyticsAdapters != null) { + futures.add(EngineAnalytics.init(analyticsAdapters)); + } + + if (bugTrackingAdapters != null) { + futures.add(EngineBugTracking.init(bugTrackingAdapters)); + } + + await Future.wait(futures); + } + + /// Initialize tracking services with configuration models + /// + /// [analyticsModel] Analytics configuration model. + /// Can be null to skip analytics initialization. + /// + /// [bugTrackingModel] Bug tracking configuration model. + /// Can be null to skip bug tracking initialization. + static Future initWithModels({ + final EngineAnalyticsModel? analyticsModel, + final EngineBugTrackingModel? bugTrackingModel, + }) async { + final futures = >[]; + + if (analyticsModel != null) { + futures.add(EngineAnalytics.initWithModel(analyticsModel)); + } + + if (bugTrackingModel != null) { + futures.add(EngineBugTracking.initWithModel(bugTrackingModel)); + } + + await Future.wait(futures); + } + + /// Initialize both services with default disabled configurations + static Future initWithDefaults() async { + await initWithModels( + analyticsModel: EngineAnalyticsModelDefault(), + bugTrackingModel: EngineBugTrackingModelDefault(), + ); + } + + /// Dispose all initialized tracking services + static Future dispose() async { + await Future.wait([ + EngineAnalytics.dispose(), + EngineBugTracking.dispose(), + ]); + } + + /// Returns true if both analytics and bug tracking are initialized + static bool get isInitialized => EngineAnalytics.isInitialized && EngineBugTracking.isInitialized; + + /// Returns true if at least one service is enabled + static bool get isEnabled => EngineAnalytics.isEnabled || EngineBugTracking.isEnabled; +} diff --git a/lib/src/logging/engine_log.dart b/lib/src/logging/engine_log.dart index 0b9369d..80bc4ae 100644 --- a/lib/src/logging/engine_log.dart +++ b/lib/src/logging/engine_log.dart @@ -8,7 +8,6 @@ import 'package:engine_tracking/engine_tracking.dart'; /// This class provides methods for logging at different levels (debug, info, warning, error, fatal) /// and integrates with Firebase Crashlytics for crash reporting or other logging services. class EngineLog { - /// The name used for all log messages static const String _name = 'ENGINE_LOG'; static Future _logWithLevel( diff --git a/lib/src/src.dart b/lib/src/src.dart index 85fabf7..9ef9bb2 100644 --- a/lib/src/src.dart +++ b/lib/src/src.dart @@ -1,6 +1,7 @@ export 'analytics/analytics.dart'; export 'bug_tracking/bug_tracking.dart'; export 'config/config.dart'; +export 'engine_tracking_initialize.dart'; export 'enums/enums.dart'; export 'logging/logging.dart'; export 'models/models.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 6bede4a..1b3cb1e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: engine_tracking description: Plugin Flutter para tracking, analytics, crashlytics e logs do Engine Framework -version: 1.4.1 +version: 1.5.0 homepage: https://stmr.tech repository: https://github.com/moreirawebmaster/engine-tracking issue_tracker: https://github.com/moreirawebmaster/engine-tracking/issues diff --git a/test/engine_tracking_initialize_test.dart b/test/engine_tracking_initialize_test.dart new file mode 100644 index 0000000..146e83f --- /dev/null +++ b/test/engine_tracking_initialize_test.dart @@ -0,0 +1,339 @@ +import 'package:engine_tracking/engine_tracking.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('EngineTrackingInitialize', () { + tearDown(() async { + await EngineTrackingInitialize.dispose(); + }); + + group('initWithAdapters', () { + test('should initialize both analytics and bug tracking with adapters', () async { + final analyticsAdapters = [ + EngineFirebaseAnalyticsAdapter(const EngineFirebaseAnalyticsConfig(enabled: false)), + EngineFaroAnalyticsAdapter( + const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + ), + ]; + + final bugTrackingAdapters = [ + EngineCrashlyticsAdapter(const EngineCrashlyticsConfig(enabled: false)), + EngineFaroBugTrackingAdapter( + const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + ), + ]; + + await EngineTrackingInitialize.initWithAdapters( + analyticsAdapters: analyticsAdapters, + bugTrackingAdapters: bugTrackingAdapters, + ); + + expect(EngineAnalytics.isInitialized, isTrue); + expect(EngineBugTracking.isInitialized, isTrue); + expect(EngineTrackingInitialize.isInitialized, isTrue); + }); + + test('should initialize only analytics when bug tracking is null', () async { + final analyticsAdapters = [ + EngineFirebaseAnalyticsAdapter(const EngineFirebaseAnalyticsConfig(enabled: false)), + ]; + + await EngineTrackingInitialize.initWithAdapters( + analyticsAdapters: analyticsAdapters, + bugTrackingAdapters: null, + ); + + expect(EngineAnalytics.isInitialized, isTrue); + expect(EngineBugTracking.isInitialized, isFalse); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + + test('should initialize only bug tracking when analytics is null', () async { + final bugTrackingAdapters = [ + EngineCrashlyticsAdapter(const EngineCrashlyticsConfig(enabled: false)), + ]; + + await EngineTrackingInitialize.initWithAdapters( + analyticsAdapters: null, + bugTrackingAdapters: bugTrackingAdapters, + ); + + expect(EngineAnalytics.isInitialized, isFalse); + expect(EngineBugTracking.isInitialized, isTrue); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + + test('should handle null adapter lists', () async { + await EngineTrackingInitialize.initWithAdapters( + analyticsAdapters: null, + bugTrackingAdapters: null, + ); + + expect(EngineAnalytics.isInitialized, isFalse); + expect(EngineBugTracking.isInitialized, isFalse); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + + test('should handle empty adapter lists', () async { + await EngineTrackingInitialize.initWithAdapters( + analyticsAdapters: [], + bugTrackingAdapters: [], + ); + + expect(EngineAnalytics.isInitialized, isTrue); + expect(EngineBugTracking.isInitialized, isTrue); + expect(EngineAnalytics.isEnabled, isFalse); + expect(EngineBugTracking.isEnabled, isFalse); + }); + }); + + group('initWithModels', () { + test('should initialize both analytics and bug tracking with models', () async { + final analyticsModel = EngineAnalyticsModel( + clarityConfig: const EngineClarityConfig(enabled: false, projectId: ''), + firebaseAnalyticsConfig: const EngineFirebaseAnalyticsConfig(enabled: false), + faroConfig: const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + googleLoggingConfig: const EngineGoogleLoggingConfig( + enabled: false, + projectId: '', + logName: '', + credentials: {}, + ), + splunkConfig: const EngineSplunkConfig( + enabled: false, + endpoint: '', + token: '', + source: '', + sourcetype: '', + index: '', + ), + ); + + final bugTrackingModel = EngineBugTrackingModel( + crashlyticsConfig: const EngineCrashlyticsConfig(enabled: false), + faroConfig: const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + googleLoggingConfig: const EngineGoogleLoggingConfig( + enabled: false, + projectId: '', + logName: '', + credentials: {}, + ), + ); + + await EngineTrackingInitialize.initWithModels( + analyticsModel: analyticsModel, + bugTrackingModel: bugTrackingModel, + ); + + expect(EngineAnalytics.isInitialized, isTrue); + expect(EngineBugTracking.isInitialized, isTrue); + expect(EngineTrackingInitialize.isInitialized, isTrue); + }); + + test('should initialize only analytics when bug tracking is null', () async { + final analyticsModel = EngineAnalyticsModel( + clarityConfig: const EngineClarityConfig(enabled: false, projectId: ''), + firebaseAnalyticsConfig: const EngineFirebaseAnalyticsConfig(enabled: false), + faroConfig: const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + googleLoggingConfig: const EngineGoogleLoggingConfig( + enabled: false, + projectId: '', + logName: '', + credentials: {}, + ), + splunkConfig: const EngineSplunkConfig( + enabled: false, + endpoint: '', + token: '', + source: '', + sourcetype: '', + index: '', + ), + ); + + await EngineTrackingInitialize.initWithModels( + analyticsModel: analyticsModel, + bugTrackingModel: null, + ); + + expect(EngineAnalytics.isInitialized, isTrue); + expect(EngineBugTracking.isInitialized, isFalse); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + + test('should initialize only bug tracking when analytics is null', () async { + final bugTrackingModel = EngineBugTrackingModel( + crashlyticsConfig: const EngineCrashlyticsConfig(enabled: false), + faroConfig: const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + googleLoggingConfig: const EngineGoogleLoggingConfig( + enabled: false, + projectId: '', + logName: '', + credentials: {}, + ), + ); + + await EngineTrackingInitialize.initWithModels( + analyticsModel: null, + bugTrackingModel: bugTrackingModel, + ); + + expect(EngineAnalytics.isInitialized, isFalse); + expect(EngineBugTracking.isInitialized, isTrue); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + + test('should handle null models', () async { + await EngineTrackingInitialize.initWithModels( + analyticsModel: null, + bugTrackingModel: null, + ); + + expect(EngineAnalytics.isInitialized, isFalse); + expect(EngineBugTracking.isInitialized, isFalse); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + }); + + group('initWithDefaults', () { + test('should initialize both services with default models', () async { + await EngineTrackingInitialize.initWithDefaults(); + + expect(EngineAnalytics.isInitialized, isTrue); + expect(EngineBugTracking.isInitialized, isTrue); + expect(EngineTrackingInitialize.isInitialized, isTrue); + expect(EngineAnalytics.isEnabled, isFalse); + expect(EngineBugTracking.isEnabled, isFalse); + }); + }); + + group('dispose', () { + test('should dispose both analytics and bug tracking', () async { + await EngineTrackingInitialize.initWithDefaults(); + + expect(EngineTrackingInitialize.isInitialized, isTrue); + + await EngineTrackingInitialize.dispose(); + + expect(EngineAnalytics.isInitialized, isFalse); + expect(EngineBugTracking.isInitialized, isFalse); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + }); + + group('isInitialized', () { + test('should return true when both services are initialized', () async { + await EngineTrackingInitialize.initWithDefaults(); + expect(EngineTrackingInitialize.isInitialized, isTrue); + }); + + test('should return false when services are not initialized', () { + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + + test('should return false when only one service is initialized', () async { + await EngineAnalytics.initWithModel(EngineAnalyticsModelDefault()); + expect(EngineTrackingInitialize.isInitialized, isFalse); + }); + }); + + group('isEnabled', () { + test('should return true when at least one service is enabled', () async { + final analyticsModel = EngineAnalyticsModel( + clarityConfig: const EngineClarityConfig(enabled: false, projectId: ''), + firebaseAnalyticsConfig: const EngineFirebaseAnalyticsConfig(enabled: true), + faroConfig: const EngineFaroConfig( + enabled: false, + endpoint: '', + appName: '', + appVersion: '', + environment: '', + apiKey: '', + namespace: '', + platform: '', + ), + googleLoggingConfig: const EngineGoogleLoggingConfig( + enabled: false, + projectId: '', + logName: '', + credentials: {}, + ), + splunkConfig: const EngineSplunkConfig( + enabled: false, + endpoint: '', + token: '', + source: '', + sourcetype: '', + index: '', + ), + ); + + await EngineTrackingInitialize.initWithModels( + analyticsModel: analyticsModel, + bugTrackingModel: EngineBugTrackingModelDefault(), + ); + + expect(EngineTrackingInitialize.isEnabled, isTrue); + }); + + test('should return false when no services are enabled', () async { + await EngineTrackingInitialize.initWithDefaults(); + expect(EngineTrackingInitialize.isEnabled, isFalse); + }); + }); + }); +} diff --git a/test/test_coverage.dart b/test/test_coverage.dart index 7a44116..6eeaa04 100644 --- a/test/test_coverage.dart +++ b/test/test_coverage.dart @@ -1,6 +1,3 @@ -// Arquivo para garantir que todas as importações sejam testadas -// Isto ajuda a manter a cobertura de testes acima de 95% - import 'package:engine_tracking/engine_tracking.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -9,7 +6,6 @@ import 'helpers/test_configs.dart'; void main() { group('Test Coverage', () { test('should import all classes correctly', () { - // Analytics expect(() => const EngineFirebaseAnalyticsConfig(enabled: true), returnsNormally); expect( () => const EngineFaroConfig( @@ -75,7 +71,6 @@ void main() { ); expect(EngineAnalyticsModelDefault.new, returnsNormally); - // Bug Tracking expect(() => const EngineCrashlyticsConfig(enabled: true), returnsNormally); expect( () => EngineBugTrackingModel( @@ -98,16 +93,16 @@ void main() { }); test('should have static methods available', () { - // Analytics static methods should be available expect(EngineAnalytics.isEnabled, isA()); expect(EngineAnalytics.isInitialized, isA()); - // Bug tracking static methods should be available expect(EngineBugTracking.isEnabled, isA()); + + expect(EngineTrackingInitialize.isEnabled, isA()); + expect(EngineTrackingInitialize.isInitialized, isA()); }); test('should handle edge cases', () { - // Test toString methods const firebaseConfig = EngineFirebaseAnalyticsConfig(enabled: true); expect(firebaseConfig.toString(), isNotEmpty); @@ -125,7 +120,7 @@ void main() { platform: '', ); expect(faroConfig.toString(), isNotEmpty); - expect(faroConfig.toString(), contains('****')); // API key should be masked + expect(faroConfig.toString(), contains('****')); const splunkConfig = EngineSplunkConfig( enabled: true, @@ -136,7 +131,7 @@ void main() { index: 'main', ); expect(splunkConfig.toString(), isNotEmpty); - expect(splunkConfig.toString(), contains('****')); // Token should be masked + expect(splunkConfig.toString(), contains('****')); const googleLoggingConfig = EngineGoogleLoggingConfig( enabled: true, @@ -145,7 +140,7 @@ void main() { credentials: {'private_key': 'secret-key'}, ); expect(googleLoggingConfig.toString(), isNotEmpty); - expect(googleLoggingConfig.toString(), contains('****')); // Credentials should be masked + expect(googleLoggingConfig.toString(), contains('****')); }); }); }