Skip to content

Commit

Permalink
feat!: Extract env switching from ConfigurationChangeNotifier into ne…
Browse files Browse the repository at this point in the history
…w class (#32)
  • Loading branch information
soeren-schmaljohann-2denker authored Feb 1, 2024
1 parent 60f3872 commit 7a91401
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 15 deletions.
49 changes: 36 additions & 13 deletions packages/apptive_grid_heinzelmen/lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,54 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';

/// A change notifier for changes in [ApptiveGridEnvironment]
class EnvironmentChangeNotifier extends ChangeNotifier {
/// Creates a new configuration change notifier for [environment]
EnvironmentChangeNotifier({
ApptiveGridEnvironment environment = ApptiveGridEnvironment.production,
this.availableEnvironments = ApptiveGridEnvironment.values,
}) : _environment = environment,
super();

ApptiveGridEnvironment _environment;

/// Returns a list of available [ApptiveGridEnvironment]s
final List<ApptiveGridEnvironment> availableEnvironments;

/// Updates [environment] and calls [notifyListeners] if the environment has changed.
/// If the environment is the current one it will not do anything
set environment(ApptiveGridEnvironment environment) {
if (environment != _environment &&
availableEnvironments.contains(environment)) {
_environment = environment;
notifyListeners();
}
}

/// The current [ApptiveGridEnvironment] environment
ApptiveGridEnvironment get environment => _environment;
}

/// A change notifier to switch configurations based on [ApptiveGridEnvironment]
class ConfigurationChangeNotifier<T> extends ChangeNotifier {
class ConfigurationChangeNotifier<T> extends EnvironmentChangeNotifier {
/// Creates a new configuration change notifier for [configurations]
/// [configurations] must contain an entry with key [environment]. By default [environment] is [ApptiveGridEnvironment.production]
ConfigurationChangeNotifier({
required Map<ApptiveGridEnvironment, T> configurations,
ApptiveGridEnvironment environment = ApptiveGridEnvironment.production,
super.environment,
}) : assert(
configurations[environment] != null,
'`configurations` must include a configuration for `environment`',
),
_configurations = configurations,
_configuration = configurations[environment]!,
_environment = environment,
super();
_configuration = configurations[environment]!;

final Map<ApptiveGridEnvironment, T> _configurations;
late T _configuration;
late ApptiveGridEnvironment _environment;

/// Updates [environment] and calls [notifyListeners] if the configuration has changed.
/// If the environment is the current one or there is matching configuration in [_configurations] it will not do anything
@override
set environment(ApptiveGridEnvironment environment) {
if (environment != _environment) {
final newConfiguration = _configurations[environment];
Expand All @@ -39,17 +65,15 @@ class ConfigurationChangeNotifier<T> extends ChangeNotifier {
/// The current [T] configuration
T get configuration => _configuration;

/// The current [ApptiveGridEnvironment] environment
ApptiveGridEnvironment get environment => _environment;

/// Returns a list of [ApptiveGridEnvironment] that have configuratinos in [_configurations]
@override
List<ApptiveGridEnvironment> get availableEnvironments =>
_configurations.keys.toList(growable: false);
}

/// A [DropdownButton] to switch the [ApptiveGridEnvironment]
/// Note this requires that there is a [Provider]<ConfigurationChangeNotifier<T>> in the Widget Tree
class EnvironmentSwitcher<T> extends StatelessWidget {
/// Note this requires that there is a [Provider]<EnvironmentChangeNotifier> in the Widget Tree
class EnvironmentSwitcher extends StatelessWidget {
/// Creates the Dropdown Button
/// Note this requires that there is a [Provider]<ConfigurationChangeNotifier> in the Widget Tree
const EnvironmentSwitcher({super.key, this.onChangeEnvironment});
Expand All @@ -60,8 +84,7 @@ class EnvironmentSwitcher<T> extends StatelessWidget {

@override
Widget build(BuildContext context) {
final configurationProvider =
context.watch<ConfigurationChangeNotifier<T>>();
final configurationProvider = context.watch<EnvironmentChangeNotifier>();
return DropdownButton<ApptiveGridEnvironment>(
value: configurationProvider.environment,
underline: const SizedBox(),
Expand Down
5 changes: 4 additions & 1 deletion packages/apptive_grid_heinzelmen/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ dependencies:
zweidenker_heinzelmen: ^2.0.0

dev_dependencies:
alchemist: ^0.7.0
alchemist:
git:
url: https://github.com/AbausG/alchemist
ref: fixes
flutter_test:
sdk: flutter
flutter_lints: ^2.0.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ Future<void> testExecutable(FutureOr<void> Function() testMain) async {
config: AlchemistConfig(
platformGoldensConfig: PlatformGoldensConfig(
enabled: !isRunningInCi,
tolerance: 0.001,
),
ciGoldensConfig: const CiGoldensConfig(
tolerance: 0.001,
),
),
run: testMain,
Expand Down
117 changes: 116 additions & 1 deletion packages/apptive_grid_heinzelmen/test/src/configuration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,121 @@ import 'package:golden_toolkit/golden_toolkit.dart' show loadAppFonts;
import 'package:provider/provider.dart';

void main() {
group('Environment Change Provider', () {
test('Initial configuration from stage', () {
final envProvider = EnvironmentChangeNotifier(
environment: ApptiveGridEnvironment.beta,
availableEnvironments: [ApptiveGridEnvironment.beta],
);

expect(envProvider.environment, equals(ApptiveGridEnvironment.beta));
expect(
envProvider.availableEnvironments,
equals([ApptiveGridEnvironment.beta]),
);
});

test('Default configuration is production', () {
final envProvider = EnvironmentChangeNotifier(
availableEnvironments: [
ApptiveGridEnvironment.production,
ApptiveGridEnvironment.beta,
],
);

expect(
envProvider.environment,
equals(ApptiveGridEnvironment.production),
);
expect(
envProvider.availableEnvironments,
equals(
[ApptiveGridEnvironment.production, ApptiveGridEnvironment.beta],
),
);
});

group('Update Environment', () {
late EnvironmentChangeNotifier envProvider;

setUp(() {
envProvider = EnvironmentChangeNotifier(
availableEnvironments: [
ApptiveGridEnvironment.production,
ApptiveGridEnvironment.beta,
],
);
});

tearDown(() {
envProvider.dispose();
});

test('Updating environment updates notifies', () async {
int listenerCallCount = 0;
final completer = Completer();

envProvider.addListener(() {
listenerCallCount++;
completer.complete();
});

expect(
envProvider.environment,
equals(ApptiveGridEnvironment.production),
);

envProvider.environment = ApptiveGridEnvironment.beta;
await completer.future;

expect(envProvider.environment, equals(ApptiveGridEnvironment.beta));
expect(listenerCallCount, 1);
});

test('Same environment does nothing', () async {
int listenerCallCount = 0;

envProvider.addListener(() {
listenerCallCount++;
});

expect(
envProvider.environment,
equals(ApptiveGridEnvironment.production),
);

envProvider.environment = ApptiveGridEnvironment.production;

expect(
envProvider.environment,
equals(ApptiveGridEnvironment.production),
);
expect(listenerCallCount, 0);
});

test('Unknown environment does nothing', () async {
int listenerCallCount = 0;

envProvider.addListener(() {
listenerCallCount++;
});

expect(
envProvider.environment,
equals(ApptiveGridEnvironment.production),
);

envProvider.environment = ApptiveGridEnvironment.alpha;

expect(
envProvider.environment,
equals(ApptiveGridEnvironment.production),
);
expect(listenerCallCount, 0);
});
});
});

group('Configuration Provider', () {
test('Initial configuration from stage', () {
final configProvider = ConfigurationChangeNotifier(
Expand Down Expand Up @@ -175,7 +290,7 @@ void main() {
target = Material(
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
home: ChangeNotifierProvider<EnvironmentChangeNotifier>(
create: (_) => configProvider,
builder: (_, __) => EnvironmentSwitcher(
onChangeEnvironment: (env) async {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7a91401

Please sign in to comment.