diff --git a/CHANGELOG.md b/CHANGELOG.md index cc7d78ecd..39cf5413e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased](https://github.com/Instabug/Instabug-Flutter/compare/v12.7.0...dev) + +### Added + +- Add `SessionReplay.getSessionReplayLink` API which retrieves the current session's replay link ([#445](hhttps://github.com/Instabug/Instabug-Flutter/pull/445)). + ## [12.7.0](https://github.com/Instabug/Instabug-Flutter/compare/v12.5.0...v12.7.0) (February 15, 2024) ### Added diff --git a/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java b/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java index cf142c0b4..2170f2c98 100644 --- a/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java +++ b/android/src/main/java/com/instabug/flutter/modules/SessionReplayApi.java @@ -1,8 +1,10 @@ package com.instabug.flutter.modules; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.instabug.flutter.generated.SessionReplayPigeon; +import com.instabug.library.OnSessionReplayLinkReady; import com.instabug.library.sessionreplay.SessionReplay; import io.flutter.plugin.common.BinaryMessenger; @@ -33,4 +35,11 @@ public void setInstabugLogsEnabled(@NonNull Boolean isEnabled) { public void setUserStepsEnabled(@NonNull Boolean isEnabled) { SessionReplay.setUserStepsEnabled(isEnabled); } + + @Override + public void getSessionReplayLink(@NonNull SessionReplayPigeon.Result result) { + SessionReplay.getSessionReplayLink(result::success); + } + + } diff --git a/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java b/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java index ace140c92..223871844 100644 --- a/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java +++ b/android/src/test/java/com/instabug/flutter/SessionReplayApiTest.java @@ -4,10 +4,13 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; import com.instabug.flutter.generated.SessionReplayPigeon; import com.instabug.flutter.modules.SessionReplayApi; import com.instabug.flutter.util.GlobalMocks; +import com.instabug.library.OnSessionReplayLinkReady; import com.instabug.library.sessionreplay.SessionReplay; import org.junit.After; @@ -81,6 +84,28 @@ public void testSetUserStepsEnabled() { mSessionReplay.verify(() -> SessionReplay.setUserStepsEnabled(true)); } + @Test + public void testGetSessionReplayLink() { + SessionReplayPigeon.Result result = mock(SessionReplayPigeon.Result.class); + String link="instabug link"; + + mSessionReplay.when(() -> SessionReplay.getSessionReplayLink(any())).thenAnswer( + invocation -> { + OnSessionReplayLinkReady callback = (OnSessionReplayLinkReady) invocation.getArguments()[0]; + callback.onSessionReplayLinkReady(link); + return callback; + }); + api.getSessionReplayLink(result); + + + mSessionReplay.verify(() -> SessionReplay.getSessionReplayLink(any())); + mSessionReplay.verifyNoMoreInteractions(); + + + verify(result, timeout(1000)).success(link); + + + } } diff --git a/example/ios/InstabugTests/SessionReplayApiTests.m b/example/ios/InstabugTests/SessionReplayApiTests.m index 1eeca6ca9..d00ef0af2 100644 --- a/example/ios/InstabugTests/SessionReplayApiTests.m +++ b/example/ios/InstabugTests/SessionReplayApiTests.m @@ -1,4 +1,6 @@ #import +#import +#import #import "OCMock/OCMock.h" #import "SessionReplayApi.h" #import "Instabug/IBGSessionReplay.h" @@ -54,4 +56,17 @@ - (void)testSetUserStepsEnabled { OCMVerify([self.mSessionReplay setUserStepsEnabled:YES]); } +- (void)testGetSessionReplayLink { + NSString *link = @"link"; + id result = ^(NSString * result, FlutterError * error) { + XCTAssertEqualObjects(result, link); + }; + + OCMStub([self.mSessionReplay sessionReplayLink]).andReturn(link); + [self.api getSessionReplayLinkWithCompletion:result]; + OCMVerify([self.mSessionReplay sessionReplayLink]); + +} + + @end diff --git a/example/lib/main.dart b/example/lib/main.dart index 31705db25..cdd183628 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -170,6 +170,23 @@ class _MyHomePageState extends State { Surveys.showSurvey('PMqUZXqarkOR2yGKiENB4w'); } + final _scaffoldKey=GlobalKey(); + + void getCurrentSessionReplaylink() async { + final result=await SessionReplay.getSessionReplayLink(); + if(result==null){ + const snackBar = SnackBar( + content: Text('No Link Found'), + ); + ScaffoldMessenger.of(_scaffoldKey.currentContext!).showSnackBar(snackBar); + }else{ + var snackBar = SnackBar( + content: Text(result), + ); + ScaffoldMessenger.of(_scaffoldKey.currentContext!).showSnackBar(snackBar); + } + } + void showFeatureRequests() { FeatureRequests.show(); } @@ -204,6 +221,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( + key: _scaffoldKey, appBar: AppBar(title: Text(widget.title)), body: SingleChildScrollView( physics: ClampingScrollPhysics(), @@ -362,6 +380,13 @@ class _MyHomePageState extends State { ), child: const Text('Dark'), ), + + + SectionTitle('Sessions Replay'), + InstabugButton( + onPressed: getCurrentSessionReplaylink, + text: 'Get current session replay link', + ), ], ), ], diff --git a/example/pubspec.lock b/example/pubspec.lock index a22d74e64..52457f4a1 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" espresso: dependency: "direct dev" description: @@ -112,10 +112,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" path: dependency: transitive description: @@ -128,10 +128,10 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" process: dependency: transitive description: @@ -157,18 +157,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" vector_math: dependency: transitive description: @@ -213,18 +213,18 @@ packages: dependency: transitive description: name: vm_service - sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 url: "https://pub.dev" source: hosted - version: "11.7.1" + version: "11.10.0" web: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" webdriver: dependency: transitive description: @@ -234,5 +234,5 @@ packages: source: hosted version: "3.0.2" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=2.10.0" diff --git a/ios/Classes/Modules/SessionReplayApi.m b/ios/Classes/Modules/SessionReplayApi.m index 600fae725..8a4c8d1bf 100644 --- a/ios/Classes/Modules/SessionReplayApi.m +++ b/ios/Classes/Modules/SessionReplayApi.m @@ -27,4 +27,11 @@ - (void)setUserStepsEnabledIsEnabled:(nonnull NSNumber *)isEnabled error:(Flutte IBGSessionReplay.userStepsEnabled = [isEnabled boolValue]; } +- (void)getSessionReplayLinkWithCompletion:(void (^)(NSString *, FlutterError *))completion { + NSString * link= IBGSessionReplay.sessionReplayLink; + completion(link,nil); + +} + + @end diff --git a/lib/src/modules/session_replay.dart b/lib/src/modules/session_replay.dart index e900f2fe5..1e5fa8e86 100644 --- a/lib/src/modules/session_replay.dart +++ b/lib/src/modules/session_replay.dart @@ -63,4 +63,15 @@ class SessionReplay { static Future setUserStepsEnabled(bool isEnabled) async { return _host.setUserStepsEnabled(isEnabled); } + + /// Retrieves current session's replay link. + /// + /// Example: + /// + /// ```dart + /// await SessionReplay.getSessionReplayLink(); + /// ``` + static Future getSessionReplayLink() async { + return _host.getSessionReplayLink(); + } } diff --git a/pigeons/session_replay.api.dart b/pigeons/session_replay.api.dart index 75983fa6f..1d4f01821 100644 --- a/pigeons/session_replay.api.dart +++ b/pigeons/session_replay.api.dart @@ -6,4 +6,8 @@ abstract class SessionReplayHostApi { void setNetworkLogsEnabled(bool isEnabled); void setInstabugLogsEnabled(bool isEnabled); void setUserStepsEnabled(bool isEnabled); + @async + String getSessionReplayLink(); + + } diff --git a/test/session_replay_test.dart b/test/session_replay_test.dart index ad334bb7b..54695e954 100644 --- a/test/session_replay_test.dart +++ b/test/session_replay_test.dart @@ -47,6 +47,7 @@ void main() { ).called(1); }); + test('[setUserStepsEnabled] should call host method', () async { const isEnabled = true; await SessionReplay.setUserStepsEnabled(isEnabled); @@ -55,4 +56,15 @@ void main() { mHost.setUserStepsEnabled(isEnabled), ).called(1); }); + + test('[getSessionReplayLink] should call host method', () async { + const link = 'link'; + when(mHost.getSessionReplayLink()).thenAnswer((_) async => link); + + final result= await SessionReplay.getSessionReplayLink(); + expect(result, link); + verify( + mHost.getSessionReplayLink(), + ).called(1); + }); }