Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Update init to take features parameter: Map<String, GBFeature> #17

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions lib/src/uptech_growthbook_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,25 @@ class UptechGrowthBookWrapper {
/// Initialize for use in app, seeds allow you to specify value of
/// toggles prior to fetching remote toggle states. These will be
/// the values if on init it fails to fetch the toggles from the remote.
Future<void> init(
{Map<String, dynamic>? seeds,
Map<String, dynamic>? overrides,
Map<String, dynamic>? attributes}) async {
Future<void> init({
// Updates to the growthbook_sdk_flutter package changed the structure of features
// This workaround allows seeded features to still be passed in using the old format,
// as well as features using the new format with GBFeature. We simply convert the
// seeds into GBFeatures and add them to the final Map<String, GBFeature>.
Map<String, GBFeature> features = const <String, GBFeature>{},
@Deprecated('Instead use "features" as Map<String, GBFeature>')
Map<String, dynamic> seeds = const <String, dynamic>{},
Map<String, dynamic>? overrides,
Map<String, dynamic>? attributes,
}) async {
Map<String, GBFeature> finalFeatures = Map.from(features);
// Convert seeds to GBFeatures and add to finalFeatures Map
if (seeds.isNotEmpty) {
seeds.forEach((key, value) {
finalFeatures[key] = GBFeature(defaultValue: value);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any tests that ensure that seeds are still valid, and that they populate growthbook correctly (because they are merged here). Should they be added?

}

_overrides.clear();
_attributes.clear();
if (overrides != null) {
Expand All @@ -40,13 +55,18 @@ class UptechGrowthBookWrapper {
_attributes.addAll(attributes);
}
_client = await _createLiveClient(
apiHost: apiHost, clientKey: clientKey, seeds: seeds);
apiHost: apiHost,
clientKey: clientKey,
features: finalFeatures,
);
await refresh();
}

/// Initialize for use in automated test suite
Future<void> initForTests(
{Map<String, dynamic>? seeds,
{Map<String, GBFeature> features = const <String, GBFeature>{},
@Deprecated('Instead use "features" as Map<String, GBFeature>')
Map<String, dynamic> seeds = const <String, dynamic>{},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does initForTests not need the combining finalFeatures and seeds functionality that is being done in init? It looks like _createTestClient gets the seeds and features is never used. Is that correct?

Map<String, dynamic>? overrides,
Map<String, dynamic>? attributes,
List<Map<String, dynamic>>? rules}) async {
Expand Down Expand Up @@ -102,17 +122,17 @@ class UptechGrowthBookWrapper {
Future<GrowthBookSDK> _createLiveClient({
required String apiHost,
required String clientKey,
required Map<String, dynamic>? seeds,
required Map<String, GBFeature> features,
}) async {
final app = await GBSDKBuilderApp(
apiKey: clientKey,
qaMode: false,
attributes: _attributes,
hostURL: apiHost,
growthBookTrackingCallBack: (gbExperiment, gbExperimentResult) {})
.initialize();
apiKey: clientKey,
qaMode: false,
attributes: _attributes,
hostURL: apiHost,
growthBookTrackingCallBack: (gbExperiment, gbExperimentResult) {},
features: features,
).initialize();

app.featuresFetchedSuccessfully(_seedsToGBFeatures(seeds: seeds));
return app;
}

Expand Down
73 changes: 38 additions & 35 deletions test/uptech_growthbook_sdk_flutter_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/widgets.dart';
import 'package:growthbook_sdk_flutter/growthbook_sdk_flutter.dart';
import 'package:uptech_growthbook_sdk_flutter/uptech_growthbook_sdk_flutter.dart';
import 'package:flutter_test/flutter_test.dart';

Expand All @@ -17,7 +18,8 @@ void main() {
final instance = UptechGrowthBookWrapper(
apiHost: 'https://cdn.growthbook.io/',
clientKey: 'sdk-rcGyvixKw6PHXQ24');
await instance.init(seeds: {'my-feature': false});
await instance
.init(features: {'my-feature': GBFeature(defaultValue: false)});
await instance.refresh();
expect(instance.isOn('my-feature'), isTrue);
});
Expand All @@ -28,7 +30,8 @@ void main() {
final instance = UptechGrowthBookWrapper(
apiHost: 'https://cdn.growthbook.io/',
clientKey: 'sdk-rcGyvixKw6PHXQ24');
await instance.init(seeds: {'my-value-feature': 'bar'});
await instance
.init(features: {'my-value-feature': GBFeature(defaultValue: 'bar')});
await instance.refresh();
expect(instance.value('my-value-feature'), 'foo');
});
Expand All @@ -38,8 +41,8 @@ void main() {
group('#isOn', () {
group('when no value is found for the feature', () {
setUp(() async {
await ToglTest.instance.initForTests(seeds: {
'some-feature-name': true,
await ToglTest.instance.initForTests(features: {
'some-feature-name': GBFeature(defaultValue: true),
});
});

Expand All @@ -50,8 +53,8 @@ void main() {

group('when a feature value is present', () {
setUp(() async {
await ToglTest.instance.initForTests(seeds: {
'some-feature-name': true,
await ToglTest.instance.initForTests(features: {
'some-feature-name': GBFeature(defaultValue: true),
});
});

Expand All @@ -77,8 +80,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -101,8 +104,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -125,8 +128,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -149,8 +152,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -173,8 +176,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -197,8 +200,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -223,8 +226,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -247,8 +250,8 @@ void main() {
setUp(() async {
const String greaterThan = '\$gt';
await ToglTest.instance.initForTests(
seeds: {
'some-feature': false,
features: {
'some-feature': GBFeature(defaultValue: false),
},
rules: [
{
Expand All @@ -273,10 +276,10 @@ void main() {
group('#value', () {
group('when no value is found for the feature', () {
setUp(() async {
await ToglTest.instance.initForTests(seeds: {
'string-value-feature': 'value',
'int-value-feature': 1,
'bool-value-feature': true,
await ToglTest.instance.initForTests(features: {
'string-value-feature': GBFeature(defaultValue: 'value'),
'int-value-feature': GBFeature(defaultValue: 1),
'bool-value-feature': GBFeature(defaultValue: true),
});
});

Expand All @@ -287,10 +290,10 @@ void main() {

group('when a feature value is present', () {
setUp(() async {
await ToglTest.instance.initForTests(seeds: {
'string-value-feature': 'value',
'int-value-feature': 1,
'bool-value-feature': true,
await ToglTest.instance.initForTests(features: {
'string-value-feature': GBFeature(defaultValue: 'value'),
'int-value-feature': GBFeature(defaultValue: 1),
'bool-value-feature': GBFeature(defaultValue: true),
});
});

Expand All @@ -306,9 +309,9 @@ void main() {
setUp(() async {
await ToglTest.instance.initForTests(
overrides: {
'string-value-feature': 'value',
'int-value-feature': 1,
'bool-value-feature': true,
'string-value-feature': GBFeature(defaultValue: 'value'),
'int-value-feature': GBFeature(defaultValue: 1),
'bool-value-feature': GBFeature(defaultValue: true),
},
);
});
Expand All @@ -325,8 +328,8 @@ void main() {

group('loadOverridesFromAssets', () {
setUp(() async {
await ToglTest.instance.initForTests(seeds: {
'some-feature-name': true,
await ToglTest.instance.initForTests(features: {
'some-feature-name': GBFeature(defaultValue: true),
});
});

Expand Down