Skip to content

Commit

Permalink
Tests and Documentation update for In-app message delegate
Browse files Browse the repository at this point in the history
  • Loading branch information
roland-misica committed Mar 7, 2024
1 parent 9e03bbb commit 265b973
Show file tree
Hide file tree
Showing 10 changed files with 872 additions and 14 deletions.
16 changes: 16 additions & 0 deletions documentation/IN_APP_MESSAGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,19 @@ In-app messages are triggered when an event is tracked based on conditions setup
If your application decides to present another UIViewController/start a new Activity right at the same time a race condition is created and the message might be displayed and immediately dismissed. Keep this in mind if the logs tell you your message was displayed but you don't see it.

> Show on `App load` displays in-app message when a `session_start` event is tracked. If you close and quickly reopen the app, it's possible that the session did not timeout and message won't be displayed. If you use manual session tracking, the message won't be displayed unless you track `session_start` event yourself.
### Custom in-app message actions
If you want to override default SDK behavior, when in-app message action is performed (button is clicked, a message is closed), or you want to add your code to be performed along with code executed by the SDK, you can set up a listener for `inAppMessageAction` using `ExponeaPlugin.inAppMessageActionStream({bool overrideDefaultBehavior = false, bool trackActions = true})`. You can override default behavior of SDK with `overrideDefaultBehavior` and `trackActions` parameters. If overrideDefaultBehavior is set to true, default in-app action will not be performed ( e.g. deep link ). If trackActions is set to false, click and close in-app events will not be tracked automatically.
The SDK will hold last inAppMessageAction and call the listener once it's set, but it's still recommended to set the listener as soon as possible.

```dart
// If overrideDefaultBehavior is set to true, default in-app action will not be performed ( e.g. deep link )
const overrideDefaultBehavior = false;
// If trackActions is set to false, click and close in-app events will not be tracked automatically
const trackActions = true;
final subscription = _plugin.inAppMessageActionStream(overrideDefaultBehavior: overrideDefaultBehavior, trackActions: trackActions).listen((inAppMessageAction) {
print(inAppMessageAction);
});
```

Don't forget to call `subscription.cancel()` when no longer needed. If you cancel subscription from stream, SDK returns back to default behavior (default in-app action will be performed and click and close in-app events will be tracked).
6 changes: 3 additions & 3 deletions lib/src/data/encoder/in_app_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ class InAppMessageEncoder {
'name': message.name,
'messageType': message.messageType,
'frequency': message.frequency,
'payload': message.payload,
'payload': message.payload?.let(jsonEncode),
'variantId': message.variantId,
'variantName': message.variantName,
'trigger': message.trigger,
'dateFilter': message.dateFilter,
'trigger': message.trigger?.let(jsonEncode),
'dateFilter': message.dateFilter?.let(jsonEncode),
'loadPriority': message.loadPriority,
'loadDelay': message.loadDelay,
'closeTimeout': message.closeTimeout,
Expand Down
3 changes: 3 additions & 0 deletions lib/src/data/encoder/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ export 'push_type.dart';
export 'recommendation.dart';
export 'token_frequency.dart';
export 'app_inbox.dart';
export 'in_app_message.dart';
export 'in_app_message_action.dart';
export 'in_app_message_button.dart';
22 changes: 11 additions & 11 deletions lib/src/data/model/in_app_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ class InAppMessage {
const InAppMessage({
required this.id,
required this.name,
required this.messageType,
this.messageType,
required this.frequency,
required this.payload,
this.payload,
required this.variantId,
required this.variantName,
required this.trigger,
required this.dateFilter,
required this.loadPriority,
required this.loadDelay,
required this.closeTimeout,
required this.payloadHtml,
required this.isHtml,
required this.hasTrackingConsent,
required this.consentCategoryTracking,
this.trigger,
this.dateFilter,
this.loadPriority,
this.loadDelay,
this.closeTimeout,
this.payloadHtml,
this.isHtml,
this.hasTrackingConsent,
this.consentCategoryTracking,
});

@override
Expand Down
95 changes: 95 additions & 0 deletions test/unit/data/in_app_message_action_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import 'package:exponea/exponea.dart';
import 'package:exponea/src/data/encoder/main.dart';
import 'package:flutter_test/flutter_test.dart';

import 'base.dart';

void main() {
group('InAppMessageAction', () {
const encode = InAppMessageActionEncoder.encode;
const decode = InAppMessageActionEncoder.decode;

final data = readMapData('in_app_message_action');
test('check data', () async {
expect(data.length, 3);
});
final noData = data[0];
final minData = data[1];
final fullData = data[2];

group('encode', () {
test('minimal', () async {
const inAppMessageAction = InAppMessageAction(
message: InAppMessage(
id: 'mock-id',
name: 'mock-name',
frequency: 'mock-frequency',
variantId: 1,
variantName: 'mock-variantName',
messageType: 'mock-messageType',
payload: {'mock-payload-param': 'mock-payload-content'},
trigger: {'mock-trigger-param': 'mock-trigger-content'},
dateFilter: {'mock-dateFilter-param': 'mock-dateFilter-content'},
loadPriority: 1,
loadDelay: 1000,
closeTimeout: 2000,
payloadHtml: 'mock-payloadHtml',
isHtml: true,
hasTrackingConsent: true,
consentCategoryTracking: 'mock-consentCategoryTracking',
),
interaction: true,
);
expect(encode(inAppMessageAction), minData);
});

test('full', () async {
const inAppMessageAction = InAppMessageAction(
message: InAppMessage(
id: 'mock-id',
name: 'mock-name',
frequency: 'mock-frequency',
variantId: 1,
variantName: 'mock-variantName',
messageType: 'mock-messageType',
payload: {'mock-payload-param': 'mock-payload-content'},
trigger: {'mock-trigger-param': 'mock-trigger-content'},
dateFilter: {'mock-dateFilter-param': 'mock-dateFilter-content'},
loadPriority: 1,
loadDelay: 1000,
closeTimeout: 2000,
payloadHtml: 'mock-payloadHtml',
isHtml: true,
hasTrackingConsent: true,
consentCategoryTracking: 'mock-consentCategoryTracking',
),
interaction: true,
button: InAppMessageButton(
text: 'button',
url: "https://a.b.c",
));
expect(encode(inAppMessageAction), fullData);
});
});

group('decode', () {
test('no data', () async {
expect(() => decode(noData), throwsStateError);
});

test('minimal', () async {
final decoded = decode(minData);
expect(decoded.message, isA<InAppMessage>());
expect(decoded.interaction, true);
expect(decoded.button, null);
});

test('full data', () async {
final decoded = decode(fullData);
expect(decoded.message, isA<InAppMessage>());
expect(decoded.interaction, true);
expect(decoded.button, isA<InAppMessageButton>());
});
});
});
}
61 changes: 61 additions & 0 deletions test/unit/data/in_app_message_button_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:exponea/exponea.dart';
import 'package:exponea/src/data/encoder/main.dart';
import 'package:flutter_test/flutter_test.dart';

import 'base.dart';

void main() {
group('InAppMessageButton', () {
const encode = InAppMessageButtonEncoder.encode;
const decode = InAppMessageButtonEncoder.decode;

final data = readMapData('in_app_message_button');
test('check data', () async {
expect(data.length, 3);
});
final noData = data[0];
final textOnlyData = data[1];
final fullData = data[2];

group('encode', () {
test('no data', () {
const inAppMessageButton = InAppMessageButton();
expect(encode(inAppMessageButton), noData);
});

test('text only', () async {
const inAppMessageButton = InAppMessageButton(text: 'button');
expect(encode(inAppMessageButton), textOnlyData);
});

test('full data', () async {
const inAppMessageButton = InAppMessageButton(text: 'button', url: 'https://a.b.c');
expect(encode(inAppMessageButton), fullData);
});
});

group('decode', () {
test('no data', () async {
const expected = InAppMessageButton();
final decoded = decode(noData);

expect(decoded.text, null);
expect(decoded.url, null);
});

test('text only', () async {
final decoded = decode(textOnlyData);

expect(decoded.text, 'button');
expect(decoded.url, null);
});

test('full data', () async {
final decoded = decode(fullData);

expect(decoded.text, 'button');
expect(decoded.url, 'https://a.b.c');
});
});
});
}
Loading

0 comments on commit 265b973

Please sign in to comment.