Skip to content

Commit

Permalink
feat(sdk): remove listeners (#100)
Browse files Browse the repository at this point in the history
* Add remove listeners API

* Add removedListenerShouldNotBeCalled test

* refactor(docs): remove listeners

* feat: changelog

---------

Co-authored-by: Sergiu Danalachi <[email protected]>
  • Loading branch information
CAMOBAP and DSergiu authored Mar 21, 2023
1 parent 19684d4 commit 60e65cc
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

# 3.6.0

- Feat: new `HCaptcha.removeAllListener` and `HCaptcha.removeOn[Success|Failure|Open]Listener(listener)` to remove all or specific listener.

# 3.5.2

- Bugfix: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState, on `verifyWithHCaptcha`
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ hCaptcha.setup().verifyWithHCaptcha()
</manifest>
```
To remove a specific listener you may use `HCaptcha.removeOn[Success|Failure|Open]Listener(listener)`.
To remove all listeners you may use `HCaptcha.removeAllListener()`.
```java
...
OnSuccessListener<HCaptchaTokenResponse> firstListener = new OnSuccessListener<HCaptchaTokenResponse>() {
@Override
public void onSuccess(HCaptchaTokenResponse response) {
...
}
};
hCaptcha.addOnSuccessListener(firstListener).verifyWithHCaptcha();
...
OnSuccessListener<HCaptchaTokenResponse> secondListener = new OnSuccessListener<HCaptchaTokenResponse>() {
@Override
public void onSuccess(HCaptchaTokenResponse response) {
...
}
};
hCaptcha.removeOnSuccessListener(firstListener)
.addOnSuccessListener(secondListener)
.verifyWithHCaptcha();
```
### Good to know
1. The listeners (`onSuccess`, `onFailure`, `onOpen`) can be called multiple times in the following cases:
1. the same client is used to invoke multiple verifications
Expand Down
4 changes: 2 additions & 2 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ android {
// See https://developer.android.com/studio/publish/versioning
// versionCode must be integer and be incremented by one for every new update
// android system uses this to prevent downgrades
versionCode 29
versionCode 30

// version number visible to the user
// should follow semantic versioning (See https://semver.org)
versionName "3.5.2"
versionName "3.6.0"

buildConfigField 'String', 'VERSION_NAME', "\"${defaultConfig.versionName}_${defaultConfig.versionCode}\""

Expand Down
25 changes: 25 additions & 0 deletions sdk/src/androidTest/java/com/hcaptcha/sdk/HCaptchaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;

import com.hcaptcha.sdk.tasks.OnSuccessListener;
import org.junit.Rule;
import org.junit.Test;

Expand Down Expand Up @@ -63,6 +64,30 @@ public void webViewSessionTimeoutSuppressed() throws Exception {
waitHCaptchaWebViewToken(latch, AWAIT_CALLBACK_MS);
}

@Test
public void removedListenerShouldNotBeCalled() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);

final OnSuccessListener<HCaptchaTokenResponse> listener1 = response -> {
fail("Listener1 should never be called");
};

final OnSuccessListener<HCaptchaTokenResponse> listener2 = response -> {
response.markUsed();
latch.countDown();
};

final ActivityScenario<TestActivity> scenario = rule.getScenario();
scenario.onActivity(activity -> HCaptcha.getClient(activity, internalConfig)
.verifyWithHCaptcha(config)
.addOnSuccessListener(listener1)
.addOnFailureListener(exception -> fail("Session timeout should not be happened"))
.removeOnSuccessListener(listener1)
.addOnSuccessListener(listener2));

waitHCaptchaWebViewToken(latch, AWAIT_CALLBACK_MS);
}

@Test
public void e2eWithDebugTokenFragmentDialog() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Expand Down
48 changes: 48 additions & 0 deletions sdk/src/main/java/com/hcaptcha/sdk/tasks/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import com.hcaptcha.sdk.HCaptchaError;
import com.hcaptcha.sdk.HCaptchaException;
import com.hcaptcha.sdk.HCaptchaLog;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -143,6 +144,18 @@ public Task<TResult> addOnSuccessListener(@NonNull final OnSuccessListener<TResu
return this;
}

/**
* Remove a success listener
* @param onSuccessListener the success listener to be removed
* @return current object
*/
public Task<TResult> removeOnSuccessListener(@NonNull final OnSuccessListener<TResult> onSuccessListener) {
if (!onSuccessListeners.remove(onSuccessListener)) {
HCaptchaLog.d("removeOnSuccessListener: %1 not found and cannot be removed", onSuccessListener);
}
return this;
}

/**
* Add a failure listener triggered when the task finishes with an exception
*
Expand All @@ -155,6 +168,18 @@ public Task<TResult> addOnFailureListener(@NonNull final OnFailureListener onFai
return this;
}

/**
* Remove a failure listener
* @param onFailureListener to be removed
* @return current object
*/
public Task<TResult> removeOnFailureListener(@NonNull final OnFailureListener onFailureListener) {
if (!onFailureListeners.remove(onFailureListener)) {
HCaptchaLog.d("removeOnFailureListener: %1 not found and cannot be removed", onFailureListener);
}
return this;
}

/**
* Add a hCaptcha open listener triggered when the hCaptcha View is displayed
*
Expand All @@ -167,6 +192,29 @@ public Task<TResult> addOnOpenListener(@NonNull final OnOpenListener onOpenListe
return this;
}

/**
* Remove a open listener
* @param onOpenListener to be removed
* @return current object
*/
public Task<TResult> removeOnOpenListener(@NonNull final OnOpenListener onOpenListener) {
if (!onOpenListeners.remove(onOpenListener)) {
HCaptchaLog.d("removeOnOpenListener: %1 not found and cannot be removed", onOpenListener);
}
return this;
}

/**
* Remove all listeners: success, failure and open listeners
* @return current object
*/
public Task<TResult> removeAllListeners() {
onSuccessListeners.clear();
onFailureListeners.clear();
onOpenListeners.clear();
return this;
}

private void tryCb() {
boolean shouldReset = false;
if (getResult() != null) {
Expand Down
34 changes: 34 additions & 0 deletions sdk/src/test/java/com/hcaptcha/sdk/HCaptchaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;

import com.hcaptcha.sdk.tasks.OnFailureListener;
import com.hcaptcha.sdk.tasks.OnOpenListener;
import com.hcaptcha.sdk.tasks.OnSuccessListener;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -45,6 +48,15 @@ public class HCaptchaTest {
@Mock
HCaptchaDialogFragment fragment;

@Mock
OnSuccessListener<HCaptchaTokenResponse> onSuccessListener;

@Mock
OnFailureListener onFailureListener;

@Mock
OnOpenListener onOpenListener;

@Captor
ArgumentCaptor<HCaptchaConfig> hCaptchaConfigCaptor;

Expand Down Expand Up @@ -219,4 +231,26 @@ public void test_verify_site_key_has_priority_over_setup_config() throws Excepti

assertEquals(HCaptchaConfigTest.MOCK_SITE_KEY, hCaptchaConfigCaptor.getValue().getSiteKey());
}

@Test
public void test_remove_listener() {
HCaptcha.getClient(fragmentActivity)
.addOnSuccessListener(onSuccessListener)
.removeOnSuccessListener(onSuccessListener);
}

@Test
public void test_remove_non_existing_listener() {
HCaptcha.getClient(fragmentActivity)
.removeOnSuccessListener(onSuccessListener);
}

@Test
public void test_clear_all_listener() {
HCaptcha.getClient(fragmentActivity)
.addOnSuccessListener(onSuccessListener)
.addOnFailureListener(onFailureListener)
.addOnOpenListener(onOpenListener)
.removeAllListeners();
}
}

0 comments on commit 60e65cc

Please sign in to comment.