Skip to content

Commit

Permalink
Merge pull request #59 from LoveCommunity/feature/scope-push
Browse files Browse the repository at this point in the history
add `scope.push`
  • Loading branch information
beeth0ven committed Jul 3, 2022
2 parents 59b0094 + ea501fe commit efd10c4
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 2 deletions.
9 changes: 9 additions & 0 deletions lib/src/scopes/scope_methods/scope_push.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

import 'dart:async';

import '../configurables/configurable.dart';
import '../scopes/scope.dart';

abstract class ScopePush {
FutureOr<Scope> push(List<Configurable> configure);
}
1 change: 1 addition & 0 deletions lib/src/scopes/scopes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
export 'configurables/configurable.dart';
export 'scope_methods/scope_get.dart';
export 'scope_methods/scope_expose.dart';
export 'scope_methods/scope_push.dart';
export 'scopes/configurable_scope.dart';
export 'scopes/scope.dart';
17 changes: 16 additions & 1 deletion lib/src/scopes/scopes/configurable_scope.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:typedef_foundation/typedef_foundation.dart';

import '../configurables/configurable.dart';
import '../scope_methods/scope_expose.dart';
import '../shared/build_scope.dart';
import 'scope.dart';

abstract class ConfigurableScope implements Scope, ScopeExpose {
@internal
factory ConfigurableScope() = _ConfigurableScopeImpl;
}

typedef _Storage = Map<Type, Map<Object?, Function>>;

class _ConfigurableScopeImpl implements ConfigurableScope {
_ConfigurableScopeImpl():
_storage = {};

final Map<Type, Map<Object?, Function>> _storage;
_ConfigurableScopeImpl._fromStorage(_Storage storage):
_storage = storage
.map((key, value) => MapEntry(key, Map.of(value)));

final _Storage _storage;

@override
T? getOrNull<T>({
Expand All @@ -40,5 +49,11 @@ class _ConfigurableScopeImpl implements ConfigurableScope {
}
_storage[T]![name] = expose;
}

@override
FutureOr<Scope> push(List<Configurable> configure) {
final scope = _ConfigurableScopeImpl._fromStorage(_storage);
return buildScope(configure, scope);
}
}

3 changes: 2 additions & 1 deletion lib/src/scopes/scopes/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import 'dart:async';

import '../configurables/configurable.dart';
import '../scope_methods/scope_get.dart';
import '../scope_methods/scope_push.dart';
import '../shared/build_scope.dart';

import 'configurable_scope.dart';

abstract class Scope implements ScopeGet {
abstract class Scope implements ScopeGet, ScopePush {
static FutureOr<Scope> root(List<Configurable> configure) => _scopeRoot(configure);
}

Expand Down
78 changes: 78 additions & 0 deletions test/scopes/scope_methods/scope_push_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

import 'package:test/test.dart';
import 'package:scopes/scopes.dart';

import '../../toolbox/mock_configurable.dart';

void main() {

test('`scope.push` return sync scope if it only has sync configuration', () async {

final parent = await Scope.root([]);

final scope = parent.push([
MockConfigurable((_) {}),
]);

expect(scope, isA<Scope>());
});

test('`scope.push` return async scope if it has async configuration', () async {

final parent = await Scope.root([]);

final scope = parent.push([
MockConfigurable((_) async {}),
]);

expect(scope, isA<Future<Scope>>());
});

test('`scope.push` returned scope has no value if value not exposed', () async {

final parent = await Scope.root([]);

final scope = await parent.push([]);

final hasValue = scope.has<String>();
final value = scope.getOrNull<String>();

expect(hasValue, false);
expect(value, null);
});

test('`scope.push` returned scope has value if value exposed', () async {

final parent = await Scope.root([]);

final scope = await parent.push([
MockConfigurable((scope) {
scope.expose<String>(expose: () => 'a');
}),
]);

final hasValue = scope.has<String>();
final value = scope.getOrNull<String>();

expect(hasValue, true);
expect(value, 'a');
});

test('`scope.push` returned scope inherit values from parent scope', () async {

final parent = await Scope.root([
MockConfigurable((scope) {
scope.expose<String>(expose: () => 'parent');
}),
]);

final scope = await parent.push([]);

final hasValue = scope.has<String>();
final value = scope.getOrNull<String>();

expect(hasValue, true);
expect(value, 'parent');
});

}
6 changes: 6 additions & 0 deletions test/scopes/scopes/scope_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'package:test/test.dart';
import 'package:scopes/scopes.dart';

Expand Down Expand Up @@ -152,4 +153,9 @@ class _MockScope implements Scope {
bool has<T>({
Object? name,
}) => throw UnimplementedError();

@override
FutureOr<Scope> push(
List<Configurable> configure,
) => throw UnimplementedError();
}
2 changes: 2 additions & 0 deletions test/scopes/scopes_test.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

import 'scope_methods/scope_push_test.dart' as scope_push_test;
import 'scopes/scope_test.dart' as scope_test;

void main() {
scope_push_test.main();
scope_test.main();
}

0 comments on commit efd10c4

Please sign in to comment.