Skip to content

Commit 47676b2

Browse files
authored
fix: Make identityRequest optional for identify, login, and logout (#61)
1 parent 5ef1728 commit 47676b2

4 files changed

Lines changed: 211 additions & 14 deletions

File tree

README.md

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ user?.getUserIdentities().then((identities) {
457457
### IDSync
458458
IDSync is mParticle’s identity framework, enabling our customers to create a unified view of the customer. To read more about IDSync, see [here](https://docs.mparticle.com/guides/idsync/introduction).
459459

460-
All IDSync calls require an `Identity Request`.
460+
IDSync calls accept an optional `Identity Request`. If no request is provided, an empty identity request is used, which mirrors the behavior of the native iOS and Android SDKs.
461461

462462
#### IdentityRequest
463463

@@ -480,7 +480,22 @@ Import the `SuccessResponse` and `FailureResponse` classes to write proper callb
480480

481481
#### Identify
482482

483-
The following is a full Identify example with error and success handling. You can adapt the following example with `login`, `modify`, and `logout`.
483+
You can call `identify` without any parameters to identify with the current user's identities:
484+
485+
```dart
486+
mpInstance?.identity
487+
.identify()
488+
.then(
489+
(IdentityApiResult successResponse) =>
490+
print("Success Response: $successResponse"),
491+
onError: (error) {
492+
var failureResponse = error as IdentityAPIErrorResponse;
493+
print("Failure Response: $failureResponse");
494+
}
495+
);
496+
```
497+
498+
Or with an identity request. The following is a full example with error and success handling. You can adapt the following example with `login`, `modify`, and `logout`.
484499

485500
```dart
486501
import 'package:mparticle_flutter_sdk/identity/identity_api_result.dart';
@@ -542,7 +557,22 @@ mpInstance?.identity
542557

543558
#### Login
544559

545-
Partial example - you can adapt the identify example above with login, modify, and logout.
560+
You can call `login` without any parameters:
561+
562+
```dart
563+
mpInstance?.identity
564+
.login()
565+
.then(
566+
(IdentityApiResult successResponse) =>
567+
print("Success Response: $successResponse"),
568+
onError: (error) {
569+
var failureResponse = error as IdentityAPIErrorResponse;
570+
print("Failure Response: $failureResponse");
571+
}
572+
);
573+
```
574+
575+
Or with an identity request:
546576

547577
```dart
548578
var identityRequest = MparticleFlutterSdk.identityRequest;
@@ -561,7 +591,6 @@ mpInstance?.identity.login(identityRequest: identityRequest).then(
561591
var failureResponse = error as IdentityAPIErrorResponse;
562592
print("Failure Response: $failureResponse");
563593
});
564-
565594
```
566595

567596
#### Modify
@@ -592,11 +621,29 @@ mpInstance?.identity
592621

593622
#### Logout
594623

595-
Partial example - you can adapt the `identify` example above with `login`, `modify`, and `logout`.
624+
You can call `logout` without any parameters, which is the most common usage:
625+
626+
```dart
627+
mpInstance?.identity
628+
.logout()
629+
.then(
630+
(IdentityApiResult successResponse) =>
631+
print("Success Response: $successResponse"),
632+
onError: (error) {
633+
var failureResponse = error as IdentityAPIErrorResponse;
634+
print("Failure Response: $failureResponse");
635+
}
636+
);
637+
```
638+
639+
Or with an identity request if needed:
596640

597641
```dart
598642
var identityRequest = MparticleFlutterSdk.identityRequest;
599-
// depending on your identity strategy, you may have identities added to your identityRequestk
643+
identityRequest
644+
.setIdentity(
645+
identityType: IdentityType.CustomerId,
646+
value: 'customerid');
600647
601648
mpInstance?.identity
602649
.logout(identityRequest: identityRequest)

ios/Classes/SwiftMparticleFlutterSdkPlugin.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,12 @@ public class SwiftMparticleFlutterSdkPlugin: NSObject, FlutterPlugin {
141141
if let callArguments = call.arguments as? [String: Any],
142142
let requestDictionary = callArguments["identityRequest"] as? [NSNumber: String] {
143143
let identityRequest = createIdentityRequest(identitiesKeyedOnType: requestDictionary)
144-
MParticle.sharedInstance().identity.modify(identityRequest, completion: {(identityResult: MPIdentityApiResult?, error: Error?) in
144+
MParticle.sharedInstance().identity.modify(identityRequest, completion: {(identityResult: MPIdentityApiResult?, error: Error?) in
145145
result(convertToIdentityResultJson(result: identityResult, error: error))
146-
})
146+
})
147+
} else {
148+
print("Incorrect argument for \(call.method) iOS method: identityRequest is required for modify")
149+
result(FlutterError(code: "INVALID_ARGUMENTS", message: "identityRequest is required for modify", details: nil))
147150
}
148151
break;
149152
// user methods

lib/mparticle_flutter_sdk.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,24 +256,24 @@ class Identity {
256256
const MethodChannel('mparticle_flutter_sdk');
257257

258258
Future<IdentityApiResult> identify({
259-
required IdentityRequest identityRequest,
259+
IdentityRequest? identityRequest,
260260
}) async {
261261
return await sendIdentityRequest(
262-
identityRequest.identities, _channel, 'identify');
262+
(identityRequest ?? IdentityRequest()).identities, _channel, 'identify');
263263
}
264264

265265
Future<IdentityApiResult> login({
266-
required IdentityRequest identityRequest,
266+
IdentityRequest? identityRequest,
267267
}) async {
268268
return await sendIdentityRequest(
269-
identityRequest.identities, _channel, 'login');
269+
(identityRequest ?? IdentityRequest()).identities, _channel, 'login');
270270
}
271271

272272
Future<IdentityApiResult> logout({
273-
required IdentityRequest identityRequest,
273+
IdentityRequest? identityRequest,
274274
}) async {
275275
return await sendIdentityRequest(
276-
identityRequest.identities, _channel, 'logout');
276+
(identityRequest ?? IdentityRequest()).identities, _channel, 'logout');
277277
}
278278

279279
Future<IdentityApiResult> modify({

test/mparticle_flutter_sdk_test.dart

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:mparticle_flutter_sdk/events/promotion_action_type.dart';
1212
import 'package:mparticle_flutter_sdk/events/impression.dart';
1313
import 'package:mparticle_flutter_sdk/events/screen_event.dart';
1414
import 'package:mparticle_flutter_sdk/identity/alias_request.dart';
15+
import 'package:mparticle_flutter_sdk/identity/identity_type.dart';
1516
import 'package:mparticle_flutter_sdk/apple/authorization_status.dart';
1617

1718
void main() {
@@ -297,6 +298,152 @@ void main() {
297298
});
298299
});
299300

301+
group('Identity API', () {
302+
test('identify with identityRequest', () async {
303+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
304+
.setMockMethodCallHandler(
305+
channel,
306+
(MethodCall call) async {
307+
methodCall = call;
308+
return '{"mpid": "123"}';
309+
},
310+
);
311+
312+
IdentityRequest request = IdentityRequest()
313+
..setIdentity(
314+
identityType: IdentityType.Email, value: 'test@example.com');
315+
await mp.identity.identify(identityRequest: request);
316+
expect(
317+
methodCall,
318+
isMethodCall('identify', arguments: {
319+
'identityRequest': {7: 'test@example.com'}
320+
}),
321+
);
322+
});
323+
324+
test('identify without identityRequest sends empty map', () async {
325+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
326+
.setMockMethodCallHandler(
327+
channel,
328+
(MethodCall call) async {
329+
methodCall = call;
330+
return '{"mpid": "123"}';
331+
},
332+
);
333+
334+
await mp.identity.identify();
335+
expect(
336+
methodCall,
337+
isMethodCall('identify', arguments: {
338+
'identityRequest': {}
339+
}),
340+
);
341+
});
342+
343+
test('login with identityRequest', () async {
344+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
345+
.setMockMethodCallHandler(
346+
channel,
347+
(MethodCall call) async {
348+
methodCall = call;
349+
return '{"mpid": "123"}';
350+
},
351+
);
352+
IdentityRequest request = IdentityRequest()
353+
..setIdentity(
354+
identityType: IdentityType.Email, value: 'login@example.com');
355+
await mp.identity.login(identityRequest: request);
356+
expect(
357+
methodCall,
358+
isMethodCall('login', arguments: {
359+
'identityRequest': {7: 'login@example.com'}
360+
}),
361+
);
362+
});
363+
364+
test('login without identityRequest sends empty map', () async {
365+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
366+
.setMockMethodCallHandler(
367+
channel,
368+
(MethodCall call) async {
369+
methodCall = call;
370+
return '{"mpid": "123"}';
371+
},
372+
);
373+
374+
await mp.identity.login();
375+
expect(
376+
methodCall,
377+
isMethodCall('login', arguments: {
378+
'identityRequest': {}
379+
}),
380+
);
381+
});
382+
383+
test('logout without identityRequest sends empty map', () async {
384+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
385+
.setMockMethodCallHandler(
386+
channel,
387+
(MethodCall call) async {
388+
methodCall = call;
389+
return '{"mpid": "123"}';
390+
},
391+
);
392+
393+
await mp.identity.logout();
394+
expect(
395+
methodCall,
396+
isMethodCall('logout', arguments: {
397+
'identityRequest': {}
398+
}),
399+
);
400+
});
401+
402+
test('modify with identityRequest', () async {
403+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
404+
.setMockMethodCallHandler(
405+
channel,
406+
(MethodCall call) async {
407+
methodCall = call;
408+
return '{"mpid": "123"}';
409+
},
410+
);
411+
412+
IdentityRequest request = IdentityRequest()
413+
..setIdentity(
414+
identityType: IdentityType.Email, value: 'new@example.com');
415+
await mp.identity.modify(identityRequest: request);
416+
expect(
417+
methodCall,
418+
isMethodCall('modify', arguments: {
419+
'identityRequest': {7: 'new@example.com'}
420+
}),
421+
);
422+
});
423+
424+
test('logout with identityRequest', () async {
425+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
426+
.setMockMethodCallHandler(
427+
channel,
428+
(MethodCall call) async {
429+
methodCall = call;
430+
return '{"mpid": "123"}';
431+
},
432+
);
433+
434+
IdentityRequest request = IdentityRequest()
435+
..setIdentity(
436+
identityType: IdentityType.CustomerId, value: 'user-123');
437+
await mp.identity.logout(identityRequest: request);
438+
expect(
439+
methodCall,
440+
isMethodCall('logout', arguments: {
441+
'identityRequest': {1: 'user-123'}
442+
}),
443+
);
444+
});
445+
});
446+
300447
group('Rokt API', () {
301448
test('rokt select placements', () async {
302449
final roktConfig = RoktConfig(

0 commit comments

Comments
 (0)