diff --git a/yoti_python_sdk/doc_scan/constants.py b/yoti_python_sdk/doc_scan/constants.py index ec2ea3a3..3cb83180 100644 --- a/yoti_python_sdk/doc_scan/constants.py +++ b/yoti_python_sdk/doc_scan/constants.py @@ -39,3 +39,11 @@ PROOF_OF_ADDRESS = "PROOF_OF_ADDRESS" WATCHLIST_SCREENING_CHECK_TYPE = "WATCHLIST_SCREENING" + +ID_DOCUMENT_EDUCATION = "ID_DOCUMENT_EDUCATION" +ID_DOCUMENT_REQUIREMENTS = "ID_DOCUMENT_REQUIREMENTS" +SUPPLEMENTARY_DOCUMENT_EDUCATION = "SUPPLEMENTARY_DOCUMENT_EDUCATION" +ZOOM_LIVENESS_EDUCATION = "ZOOM_LIVENESS_EDUCATION" +STATIC_LIVENESS_EDUCATION = "STATIC_LIVENESS_EDUCATION" +FACE_CAPTURE_EDUCATION = "FACE_CAPTURE_EDUCATION" +FLOW_COMPLETION = "FLOW_COMPLETION" diff --git a/yoti_python_sdk/doc_scan/session/create/sdk_config.py b/yoti_python_sdk/doc_scan/session/create/sdk_config.py index 37cde6b5..eeb80ff0 100644 --- a/yoti_python_sdk/doc_scan/session/create/sdk_config.py +++ b/yoti_python_sdk/doc_scan/session/create/sdk_config.py @@ -23,6 +23,7 @@ def __init__( error_url, allow_handoff=None, privacy_policy_url=None, + suppressed_screens=None, ): """ :param allowed_capture_methods: the allowed capture methods @@ -45,6 +46,8 @@ def __init__( :type privacy_policy_url: str :param allow_handoff: boolean flag for allow_handoff :type allow_handoff: bool + :param suppressed_screens: list of screen names to be suppressed + :type suppressed_screens: list[str] """ self.__allowed_capture_methods = allowed_capture_methods self.__primary_colour = primary_colour @@ -56,6 +59,7 @@ def __init__( self.__error_url = error_url self.__privacy_policy_url = privacy_policy_url self.__allow_handoff = allow_handoff + self.__suppressed_screens = suppressed_screens @property def allowed_capture_methods(self): @@ -148,6 +152,16 @@ def allow_handoff(self): """ return self.__allow_handoff + @property + def suppressed_screens(self): + """ + The list of screen names that should be omitted from the IDV flow + + :return: the list of suppressed screens + :rtype: list[str] or None + """ + return self.__suppressed_screens + def to_json(self): return remove_null_values( { @@ -161,6 +175,7 @@ def to_json(self): "error_url": self.error_url, "privacy_policy_url": self.privacy_policy_url, "allow_handoff": self.allow_handoff, + "suppressed_screens": self.suppressed_screens, } ) @@ -181,6 +196,7 @@ def __init__(self): self.__error_url = None self.__privacy_policy_url = None self.__allow_handoff = None + self.__suppressed_screens = None def with_allowed_capture_methods(self, allowed_capture_methods): """ @@ -320,6 +336,39 @@ def with_allow_handoff(self, flag): self.__allow_handoff = flag return self + def with_suppressed_screens(self, suppressed_screens): + """ + Sets the list of screens to be suppressed from the IDV flow. + + Valid screen names are defined in + :mod:`yoti_python_sdk.doc_scan.constants`: + ``ID_DOCUMENT_EDUCATION``, ``ID_DOCUMENT_REQUIREMENTS``, + ``SUPPLEMENTARY_DOCUMENT_EDUCATION``, ``ZOOM_LIVENESS_EDUCATION``, + ``STATIC_LIVENESS_EDUCATION``, ``FACE_CAPTURE_EDUCATION``, + ``FLOW_COMPLETION``. + + :param suppressed_screens: the list of screens to suppress + :type suppressed_screens: list[str] + :return: the builder + :rtype: SdkConfigBuilder + """ + self.__suppressed_screens = list(suppressed_screens) if suppressed_screens is not None else None + return self + + def with_suppressed_screen(self, screen): + """ + Adds a single screen name to the list of suppressed screens. + + :param screen: the screen name to suppress + :type screen: str + :return: the builder + :rtype: SdkConfigBuilder + """ + if self.__suppressed_screens is None: + self.__suppressed_screens = [] + self.__suppressed_screens.append(screen) + return self + def build(self): return SdkConfig( self.__allowed_capture_methods, @@ -332,4 +381,5 @@ def build(self): self.__error_url, self.__allow_handoff, self.__privacy_policy_url, + self.__suppressed_screens, ) diff --git a/yoti_python_sdk/tests/doc_scan/session/create/test_sdk_config.py b/yoti_python_sdk/tests/doc_scan/session/create/test_sdk_config.py index d621a441..ba00902e 100644 --- a/yoti_python_sdk/tests/doc_scan/session/create/test_sdk_config.py +++ b/yoti_python_sdk/tests/doc_scan/session/create/test_sdk_config.py @@ -1,6 +1,7 @@ import json import unittest +from yoti_python_sdk.doc_scan import constants from yoti_python_sdk.doc_scan.session.create import SdkConfigBuilder from yoti_python_sdk.doc_scan.session.create.sdk_config import SdkConfig from yoti_python_sdk.utils import YotiEncoder @@ -16,6 +17,10 @@ class SdkConfigTest(unittest.TestCase): SOME_ERROR_URL = "https://mysite.com/yoti/error" SOME_PRIVACY_POLICY_URL = "https://mysite.com/privacy" SOME_ALLOW_HANDOFF = True + SOME_SUPPRESSED_SCREENS = [ + constants.ID_DOCUMENT_EDUCATION, + constants.FLOW_COMPLETION, + ] def test_should_build_correctly(self): result = ( @@ -30,6 +35,7 @@ def test_should_build_correctly(self): .with_error_url(self.SOME_ERROR_URL) .with_privacy_policy_url(self.SOME_PRIVACY_POLICY_URL) .with_allow_handoff(self.SOME_ALLOW_HANDOFF) + .with_suppressed_screens(self.SOME_SUPPRESSED_SCREENS) .build() ) @@ -44,6 +50,7 @@ def test_should_build_correctly(self): assert result.error_url is self.SOME_ERROR_URL assert result.privacy_policy_url is self.SOME_PRIVACY_POLICY_URL assert result.allow_handoff is True + assert result.suppressed_screens == self.SOME_SUPPRESSED_SCREENS def test_should_allows_camera(self): result = SdkConfigBuilder().with_allows_camera().build() @@ -78,6 +85,69 @@ def test_should_serialize_to_json_without_error(self): s = json.dumps(result, cls=YotiEncoder) assert s is not None and s != "" + def test_suppressed_screens_default_to_none(self): + result = SdkConfigBuilder().with_allows_camera().build() + + assert result.suppressed_screens is None + + def test_should_add_individual_suppressed_screens(self): + result = ( + SdkConfigBuilder() + .with_suppressed_screen(constants.ID_DOCUMENT_EDUCATION) + .with_suppressed_screen(constants.FLOW_COMPLETION) + .build() + ) + + assert result.suppressed_screens == [ + constants.ID_DOCUMENT_EDUCATION, + constants.FLOW_COMPLETION, + ] + + def test_suppressed_screens_serialized_when_set(self): + result = ( + SdkConfigBuilder() + .with_suppressed_screens(self.SOME_SUPPRESSED_SCREENS) + .build() + ) + + s = json.dumps(result, cls=YotiEncoder) + parsed = json.loads(s) + + assert "suppressed_screens" in parsed + assert parsed["suppressed_screens"] == self.SOME_SUPPRESSED_SCREENS + + def test_suppressed_screens_omitted_when_not_set(self): + result = SdkConfigBuilder().with_allows_camera().build() + + s = json.dumps(result, cls=YotiEncoder) + parsed = json.loads(s) + + assert "suppressed_screens" not in parsed + + def test_with_suppressed_screens_returns_builder(self): + builder = SdkConfigBuilder() + result = builder.with_suppressed_screens(self.SOME_SUPPRESSED_SCREENS) + + assert result is builder + + def test_with_suppressed_screen_returns_builder(self): + builder = SdkConfigBuilder() + result = builder.with_suppressed_screen(constants.FLOW_COMPLETION) + + assert result is builder + + def test_suppressed_screen_constants_defined(self): + assert constants.ID_DOCUMENT_EDUCATION == "ID_DOCUMENT_EDUCATION" + assert constants.ID_DOCUMENT_REQUIREMENTS == "ID_DOCUMENT_REQUIREMENTS" + assert ( + constants.SUPPLEMENTARY_DOCUMENT_EDUCATION + == "SUPPLEMENTARY_DOCUMENT_EDUCATION" + ) + assert constants.ZOOM_LIVENESS_EDUCATION == "ZOOM_LIVENESS_EDUCATION" + assert constants.STATIC_LIVENESS_EDUCATION == "STATIC_LIVENESS_EDUCATION" + assert constants.FACE_CAPTURE_EDUCATION == "FACE_CAPTURE_EDUCATION" + assert constants.FLOW_COMPLETION == "FLOW_COMPLETION" + if __name__ == "__main__": unittest.main()