Skip to content

Commit 60e58d2

Browse files
committed
add unit test
1 parent f2bcdf6 commit 60e58d2

File tree

5 files changed

+151
-4
lines changed

5 files changed

+151
-4
lines changed

lib/visitor.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ class Visitor with EmotionAiDelegate {
349349

350350
// Get consent
351351
bool getConsent() {
352-
sessionDuration = DateTime.now();
353352
return _hasConsented;
354353
}
355354

lib/visitor/strategy/default_strategy.dart

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class DefaultStrategy implements IVisitor {
4343
}
4444

4545
// Activate
46-
Future<void> _sendActivate(
46+
/* Future<void> _sendActivate(
4747
Modification pModification, bool isDuplicated) async {
4848
// Check if the callback is defined
4949
ExposedFlag? exposedFlag;
@@ -97,6 +97,81 @@ class DefaultStrategy implements IVisitor {
9797
" status code = ${activateResponse.statusCode.toString()}");
9898
}
9999
});
100+
} */
101+
102+
Future<void> _sendActivate(
103+
Modification modification,
104+
bool isDuplicated,
105+
) async {
106+
// Getconfig et le callback
107+
final config = Flagship.sharedInstance().getConfiguration();
108+
final onExposed = config?.onVisitorExposed;
109+
110+
// Prepare exposure object
111+
ExposedFlag? exposedFlag;
112+
VisitorExposed? exposedVisitor;
113+
if (onExposed != null) {
114+
exposedFlag = ExposedFlag(
115+
modification.key,
116+
modification.value,
117+
modification.defaultValue,
118+
FlagMetadata.withMap(modification.toJsonInformation()),
119+
);
120+
exposedVisitor = VisitorExposed(
121+
visitor.visitorId,
122+
visitor.anonymousId,
123+
visitor.getContext(),
124+
);
125+
}
126+
127+
// When deduplicated
128+
if (isDuplicated) {
129+
if (onExposed != null && exposedFlag != null && exposedVisitor != null) {
130+
exposedFlag.alreadyActivatedCampaign = true;
131+
onExposed(exposedVisitor, exposedFlag);
132+
}
133+
print('Skip the activate: Flag already activated.');
134+
return;
135+
}
136+
137+
// When not duplicated
138+
final String? flagJson =
139+
exposedFlag != null ? jsonEncode(exposedFlag) : null;
140+
final String? visitorJson =
141+
exposedVisitor != null ? jsonEncode(exposedVisitor) : null;
142+
143+
final activateHit = Activate(
144+
modification,
145+
visitor.visitorId,
146+
visitor.anonymousId,
147+
Flagship.sharedInstance().envId ?? '',
148+
flagJson,
149+
visitorJson,
150+
);
151+
152+
// Log interne pour troubleshooting
153+
DataUsageTracking.sharedInstance().processTroubleShootingHits(
154+
CriticalPoints.VISITOR_SEND_ACTIVATE.name,
155+
visitor,
156+
activateHit,
157+
);
158+
159+
// Envoi du hit
160+
try {
161+
final response = await visitor.trackingManager?.sendActivate(activateHit);
162+
final status = response?.statusCode ?? -1;
163+
if (status < 200 || status >= 300) {
164+
Flagship.logger(
165+
Level.ERROR,
166+
'ACTIVATE_FAILED: status code = $status',
167+
);
168+
}
169+
} catch (e, stack) {
170+
Flagship.logger(
171+
Level.ERROR,
172+
'ACTIVATE_FAILED: exception = $e\n$stack',
173+
);
174+
}
100175
}
101176

102177
@override

lib/visitor/visitor_delegate.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:flagship/visitor/strategy/no_consent_strategy.dart';
99
import 'package:flagship/visitor/strategy/not_ready_strategy.dart';
1010
import 'package:flagship/visitor/strategy/panic_strategy.dart';
1111
import 'package:flagship/flagship.dart';
12+
import 'package:flutter/material.dart';
1213
import '../visitor.dart';
1314

1415
class VisitorDelegate implements IVisitor {
@@ -149,7 +150,6 @@ class VisitorDelegate implements IVisitor {
149150
"--------- Session time duration is ${elapsed.inSeconds} ------------");
150151

151152
try {
152-
// -- 1. Session expirée ---------------------------------------------------
153153
if (elapsed > FSSessionVisitor) {
154154
_activatedVariations
155155
..clear()

test/activate_test.dart

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,44 @@
1+
import 'package:flagship/api/service.dart';
2+
import 'package:flagship/cache/default_cache.dart';
3+
import 'package:flagship/decision/api_manager.dart';
14
import 'package:flagship/flagship.dart';
25
import 'package:flagship/flagship_config.dart';
6+
import 'package:flagship/flagship_version.dart';
37
import 'package:flagship/model/exposed_flag.dart';
48
import 'package:flagship/model/flag.dart';
59
import 'package:flagship/model/modification.dart';
610
import 'package:flagship/model/visitor_exposed.dart';
11+
import 'package:flagship/tracking/tracking_manager.dart';
12+
import 'package:flagship/tracking/tracking_manager_config.dart';
13+
import 'package:flagship/tracking/tracking_manager_continuous_strategies.dart';
714
import 'package:flagship/visitor/strategy/default_strategy.dart';
815
import 'package:flutter/widgets.dart';
916
import 'package:flutter_test/flutter_test.dart';
1017
import 'package:flagship/hits/activate.dart';
18+
import 'package:mockito/annotations.dart';
19+
import 'package:mockito/mockito.dart';
1120
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
1221
import 'package:shared_preferences/shared_preferences.dart';
1322

1423
import 'fake_path_provider_platform.dart';
1524
import 'test_tools.dart';
25+
import 'package:http/http.dart' as http;
26+
import 'service_test.mocks.dart';
27+
import 'test_tools.dart';
1628

29+
@GenerateMocks([Service])
1730
void main() {
18-
WidgetsFlutterBinding.ensureInitialized();
31+
MockService fakeService = MockService();
32+
33+
MockService fakeTrackingService = MockService();
34+
35+
TrackingManager fakeTrackingMgr = TrackingManageContinuousStrategy(
36+
fakeTrackingService, TrackingManagerConfig(), DefaultCacheHitImp());
37+
38+
ApiManager fakeApi = ApiManager(fakeService);
1939
PathProviderPlatform.instance = FakePathProviderPlatform();
2040
ToolsTest.sqfliteTestInit();
41+
WidgetsFlutterBinding.ensureInitialized();
2142
SharedPreferences.setMockInitialValues({});
2243

2344
test("Activate with Modification object ", () {
@@ -111,4 +132,51 @@ void main() {
111132
var eF = ExposedFlag("key", 12, 12, FlagMetadata.withMap({}));
112133
expect(eF.metadata().campaignId, "");
113134
});
135+
136+
test(' Test is Deduplicated', () async {
137+
/// prepare response
138+
when(fakeTrackingService.sendHttpRequest(RequestType.Post,
139+
'https://decision.flagship.io/v2/activate', any, any,
140+
timeoutMs: TIMEOUT_REQUEST))
141+
.thenAnswer((_) async {
142+
return http.Response("mock", 200);
143+
});
144+
145+
var testConfig = ConfigBuilder().withOnVisitorExposed((v, f) {
146+
if (v.id == "testV") {
147+
expect(f.metadata().campaignId, "campaignId");
148+
expect(v.id, "expoVisitorObj");
149+
expect(f.alreadyActivatedCampaign, true);
150+
}
151+
}).build();
152+
153+
Flagship.start("bkk9glocmjcg0vtmdlrr", "apiKey", config: testConfig);
154+
155+
var testV = Flagship.newVisitor(visitorId: "testV", hasConsented: true)
156+
.withContext({"expoKey": "expoVal"}).build();
157+
158+
testV.trackingManager = fakeTrackingMgr;
159+
testV.config.decisionManager = fakeApi;
160+
161+
// Create a default strategy
162+
var dfltStrategy = DefaultStrategy(testV);
163+
164+
Modification itemModif = Modification(
165+
"key1",
166+
"campaignId",
167+
"campName",
168+
"variationGroupId",
169+
"vargName",
170+
"variationId",
171+
"varName",
172+
true,
173+
"ab",
174+
"slug",
175+
12);
176+
177+
dfltStrategy.activateFlag(itemModif, isDuplicated: true);
178+
var tr = dfltStrategy.visitor.trackingManager
179+
as TrackingManageContinuousStrategy;
180+
expect(tr.activatePool.fsQueue.length, 0);
181+
});
114182
}

test/tracking_manager_test.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ Future<void> main() async {
8585
mockFlag = vMock.getFlag("key_A");
8686
var mockVal = mockFlag.value("defaultValue", visitorExposed: false);
8787
expect(mockVal, "val_A");
88+
vMock.sessionDuration =
89+
DateTime.now().subtract(const Duration(minutes: 35));
8890
await mockFlag.visitorExposed();
8991
}
9092

@@ -105,7 +107,10 @@ Future<void> main() async {
105107
mockFlagBis = vMock.getFlag("key_A");
106108
var mockValBis = mockFlagBis.value("defaultValue", visitorExposed: false);
107109
expect(mockValBis, "val_A");
110+
vMock.sessionDuration =
111+
DateTime.now().subtract(const Duration(minutes: 35));
108112
await mockFlagBis.visitorExposed();
113+
109114
// After sucess the pool should be empty
110115
expect(
111116
(vMock.trackingManager as TrackingManageContinuousStrategy)

0 commit comments

Comments
 (0)