Skip unit tests which require optional dependencies (#9031)
If we are lacking an optional dependency, skip the tests that rely on it.
This commit is contained in:
parent
eee3c3c52f
commit
8d3d264052
|
@ -0,0 +1 @@
|
||||||
|
Fix running unit tests when optional dependencies are not installed.
|
|
@ -24,7 +24,6 @@ import pymacaroons
|
||||||
from twisted.web.resource import Resource
|
from twisted.web.resource import Resource
|
||||||
|
|
||||||
from synapse.api.errors import RedirectException
|
from synapse.api.errors import RedirectException
|
||||||
from synapse.handlers.oidc_handler import OidcError
|
|
||||||
from synapse.handlers.sso import MappingException
|
from synapse.handlers.sso import MappingException
|
||||||
from synapse.rest.client.v1 import login
|
from synapse.rest.client.v1 import login
|
||||||
from synapse.rest.synapse.client.pick_username import pick_username_resource
|
from synapse.rest.synapse.client.pick_username import pick_username_resource
|
||||||
|
@ -34,6 +33,14 @@ from synapse.types import UserID
|
||||||
from tests.test_utils import FakeResponse, simple_async_mock
|
from tests.test_utils import FakeResponse, simple_async_mock
|
||||||
from tests.unittest import HomeserverTestCase, override_config
|
from tests.unittest import HomeserverTestCase, override_config
|
||||||
|
|
||||||
|
try:
|
||||||
|
import authlib # noqa: F401
|
||||||
|
|
||||||
|
HAS_OIDC = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_OIDC = False
|
||||||
|
|
||||||
|
|
||||||
# These are a few constants that are used as config parameters in the tests.
|
# These are a few constants that are used as config parameters in the tests.
|
||||||
ISSUER = "https://issuer/"
|
ISSUER = "https://issuer/"
|
||||||
CLIENT_ID = "test-client-id"
|
CLIENT_ID = "test-client-id"
|
||||||
|
@ -113,6 +120,9 @@ async def get_json(url):
|
||||||
|
|
||||||
|
|
||||||
class OidcHandlerTestCase(HomeserverTestCase):
|
class OidcHandlerTestCase(HomeserverTestCase):
|
||||||
|
if not HAS_OIDC:
|
||||||
|
skip = "requires OIDC"
|
||||||
|
|
||||||
def default_config(self):
|
def default_config(self):
|
||||||
config = super().default_config()
|
config = super().default_config()
|
||||||
config["public_baseurl"] = BASE_URL
|
config["public_baseurl"] = BASE_URL
|
||||||
|
@ -458,6 +468,8 @@ class OidcHandlerTestCase(HomeserverTestCase):
|
||||||
self.assertRenderedError("fetch_error")
|
self.assertRenderedError("fetch_error")
|
||||||
|
|
||||||
# Handle code exchange failure
|
# Handle code exchange failure
|
||||||
|
from synapse.handlers.oidc_handler import OidcError
|
||||||
|
|
||||||
self.handler._exchange_code = simple_async_mock(
|
self.handler._exchange_code = simple_async_mock(
|
||||||
raises=OidcError("invalid_request")
|
raises=OidcError("invalid_request")
|
||||||
)
|
)
|
||||||
|
@ -538,6 +550,8 @@ class OidcHandlerTestCase(HomeserverTestCase):
|
||||||
body=b'{"error": "foo", "error_description": "bar"}',
|
body=b'{"error": "foo", "error_description": "bar"}',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
from synapse.handlers.oidc_handler import OidcError
|
||||||
|
|
||||||
exc = self.get_failure(self.handler._exchange_code(code), OidcError)
|
exc = self.get_failure(self.handler._exchange_code(code), OidcError)
|
||||||
self.assertEqual(exc.value.error, "foo")
|
self.assertEqual(exc.value.error, "foo")
|
||||||
self.assertEqual(exc.value.error_description, "bar")
|
self.assertEqual(exc.value.error_description, "bar")
|
||||||
|
@ -829,6 +843,9 @@ class OidcHandlerTestCase(HomeserverTestCase):
|
||||||
|
|
||||||
|
|
||||||
class UsernamePickerTestCase(HomeserverTestCase):
|
class UsernamePickerTestCase(HomeserverTestCase):
|
||||||
|
if not HAS_OIDC:
|
||||||
|
skip = "requires OIDC"
|
||||||
|
|
||||||
servlets = [login.register_servlets]
|
servlets = [login.register_servlets]
|
||||||
|
|
||||||
def default_config(self):
|
def default_config(self):
|
||||||
|
|
|
@ -4,7 +4,10 @@ import urllib.parse
|
||||||
|
|
||||||
from mock import Mock
|
from mock import Mock
|
||||||
|
|
||||||
import jwt
|
try:
|
||||||
|
import jwt
|
||||||
|
except ImportError:
|
||||||
|
jwt = None
|
||||||
|
|
||||||
import synapse.rest.admin
|
import synapse.rest.admin
|
||||||
from synapse.appservice import ApplicationService
|
from synapse.appservice import ApplicationService
|
||||||
|
@ -460,6 +463,9 @@ class CASTestCase(unittest.HomeserverTestCase):
|
||||||
|
|
||||||
|
|
||||||
class JWTTestCase(unittest.HomeserverTestCase):
|
class JWTTestCase(unittest.HomeserverTestCase):
|
||||||
|
if not jwt:
|
||||||
|
skip = "requires jwt"
|
||||||
|
|
||||||
servlets = [
|
servlets = [
|
||||||
synapse.rest.admin.register_servlets_for_client_rest_resource,
|
synapse.rest.admin.register_servlets_for_client_rest_resource,
|
||||||
login.register_servlets,
|
login.register_servlets,
|
||||||
|
@ -628,6 +634,9 @@ class JWTTestCase(unittest.HomeserverTestCase):
|
||||||
# RSS256, with a public key configured in synapse as "jwt_secret", and tokens
|
# RSS256, with a public key configured in synapse as "jwt_secret", and tokens
|
||||||
# signed by the private key.
|
# signed by the private key.
|
||||||
class JWTPubKeyTestCase(unittest.HomeserverTestCase):
|
class JWTPubKeyTestCase(unittest.HomeserverTestCase):
|
||||||
|
if not jwt:
|
||||||
|
skip = "requires jwt"
|
||||||
|
|
||||||
servlets = [
|
servlets = [
|
||||||
login.register_servlets,
|
login.register_servlets,
|
||||||
]
|
]
|
||||||
|
|
|
@ -26,8 +26,10 @@ from synapse.rest.oidc import OIDCResource
|
||||||
from synapse.types import JsonDict, UserID
|
from synapse.types import JsonDict, UserID
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
from tests.handlers.test_oidc import HAS_OIDC
|
||||||
from tests.rest.client.v1.utils import TEST_OIDC_CONFIG
|
from tests.rest.client.v1.utils import TEST_OIDC_CONFIG
|
||||||
from tests.server import FakeChannel
|
from tests.server import FakeChannel
|
||||||
|
from tests.unittest import override_config, skip_unless
|
||||||
|
|
||||||
|
|
||||||
class DummyRecaptchaChecker(UserInteractiveAuthChecker):
|
class DummyRecaptchaChecker(UserInteractiveAuthChecker):
|
||||||
|
@ -158,20 +160,22 @@ class UIAuthTests(unittest.HomeserverTestCase):
|
||||||
|
|
||||||
def default_config(self):
|
def default_config(self):
|
||||||
config = super().default_config()
|
config = super().default_config()
|
||||||
|
|
||||||
# we enable OIDC as a way of testing SSO flows
|
|
||||||
oidc_config = {}
|
|
||||||
oidc_config.update(TEST_OIDC_CONFIG)
|
|
||||||
oidc_config["allow_existing_users"] = True
|
|
||||||
|
|
||||||
config["oidc_config"] = oidc_config
|
|
||||||
config["public_baseurl"] = "https://synapse.test"
|
config["public_baseurl"] = "https://synapse.test"
|
||||||
|
|
||||||
|
if HAS_OIDC:
|
||||||
|
# we enable OIDC as a way of testing SSO flows
|
||||||
|
oidc_config = {}
|
||||||
|
oidc_config.update(TEST_OIDC_CONFIG)
|
||||||
|
oidc_config["allow_existing_users"] = True
|
||||||
|
config["oidc_config"] = oidc_config
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def create_resource_dict(self):
|
def create_resource_dict(self):
|
||||||
resource_dict = super().create_resource_dict()
|
resource_dict = super().create_resource_dict()
|
||||||
# mount the OIDC resource at /_synapse/oidc
|
if HAS_OIDC:
|
||||||
resource_dict["/_synapse/oidc"] = OIDCResource(self.hs)
|
# mount the OIDC resource at /_synapse/oidc
|
||||||
|
resource_dict["/_synapse/oidc"] = OIDCResource(self.hs)
|
||||||
return resource_dict
|
return resource_dict
|
||||||
|
|
||||||
def prepare(self, reactor, clock, hs):
|
def prepare(self, reactor, clock, hs):
|
||||||
|
@ -380,6 +384,8 @@ class UIAuthTests(unittest.HomeserverTestCase):
|
||||||
# Note that *no auth* information is provided, not even a session iD!
|
# Note that *no auth* information is provided, not even a session iD!
|
||||||
self.delete_device(self.user_tok, self.device_id, 200)
|
self.delete_device(self.user_tok, self.device_id, 200)
|
||||||
|
|
||||||
|
@skip_unless(HAS_OIDC, "requires OIDC")
|
||||||
|
@override_config({"oidc_config": TEST_OIDC_CONFIG})
|
||||||
def test_does_not_offer_password_for_sso_user(self):
|
def test_does_not_offer_password_for_sso_user(self):
|
||||||
login_resp = self.helper.login_via_oidc("username")
|
login_resp = self.helper.login_via_oidc("username")
|
||||||
user_tok = login_resp["access_token"]
|
user_tok = login_resp["access_token"]
|
||||||
|
@ -393,13 +399,13 @@ class UIAuthTests(unittest.HomeserverTestCase):
|
||||||
self.assertEqual(flows, [{"stages": ["m.login.sso"]}])
|
self.assertEqual(flows, [{"stages": ["m.login.sso"]}])
|
||||||
|
|
||||||
def test_does_not_offer_sso_for_password_user(self):
|
def test_does_not_offer_sso_for_password_user(self):
|
||||||
# now call the device deletion API: we should get the option to auth with SSO
|
|
||||||
# and not password.
|
|
||||||
channel = self.delete_device(self.user_tok, self.device_id, 401)
|
channel = self.delete_device(self.user_tok, self.device_id, 401)
|
||||||
|
|
||||||
flows = channel.json_body["flows"]
|
flows = channel.json_body["flows"]
|
||||||
self.assertEqual(flows, [{"stages": ["m.login.password"]}])
|
self.assertEqual(flows, [{"stages": ["m.login.password"]}])
|
||||||
|
|
||||||
|
@skip_unless(HAS_OIDC, "requires OIDC")
|
||||||
|
@override_config({"oidc_config": TEST_OIDC_CONFIG})
|
||||||
def test_offers_both_flows_for_upgraded_user(self):
|
def test_offers_both_flows_for_upgraded_user(self):
|
||||||
"""A user that had a password and then logged in with SSO should get both flows
|
"""A user that had a password and then logged in with SSO should get both flows
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -26,8 +26,15 @@ from twisted.test.proto_helpers import AccumulatingProtocol
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
from tests.server import FakeTransport
|
from tests.server import FakeTransport
|
||||||
|
|
||||||
|
try:
|
||||||
|
import lxml
|
||||||
|
except ImportError:
|
||||||
|
lxml = None
|
||||||
|
|
||||||
|
|
||||||
class URLPreviewTests(unittest.HomeserverTestCase):
|
class URLPreviewTests(unittest.HomeserverTestCase):
|
||||||
|
if not lxml:
|
||||||
|
skip = "url preview feature requires lxml"
|
||||||
|
|
||||||
hijack_auth = True
|
hijack_auth = True
|
||||||
user_id = "@test:user"
|
user_id = "@test:user"
|
||||||
|
|
|
@ -20,8 +20,16 @@ from synapse.rest.media.v1.preview_url_resource import (
|
||||||
|
|
||||||
from . import unittest
|
from . import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
import lxml
|
||||||
|
except ImportError:
|
||||||
|
lxml = None
|
||||||
|
|
||||||
|
|
||||||
class PreviewTestCase(unittest.TestCase):
|
class PreviewTestCase(unittest.TestCase):
|
||||||
|
if not lxml:
|
||||||
|
skip = "url preview feature requires lxml"
|
||||||
|
|
||||||
def test_long_summarize(self):
|
def test_long_summarize(self):
|
||||||
example_paras = [
|
example_paras = [
|
||||||
"""Tromsø (Norwegian pronunciation: [ˈtrʊmsœ] ( listen); Northern Sami:
|
"""Tromsø (Norwegian pronunciation: [ˈtrʊmsœ] ( listen); Northern Sami:
|
||||||
|
@ -137,6 +145,9 @@ class PreviewTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class PreviewUrlTestCase(unittest.TestCase):
|
class PreviewUrlTestCase(unittest.TestCase):
|
||||||
|
if not lxml:
|
||||||
|
skip = "url preview feature requires lxml"
|
||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
html = """
|
html = """
|
||||||
<html>
|
<html>
|
||||||
|
|
|
@ -20,7 +20,7 @@ import hmac
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Dict, Iterable, Optional, Tuple, Type, TypeVar, Union
|
from typing import Callable, Dict, Iterable, Optional, Tuple, Type, TypeVar, Union
|
||||||
|
|
||||||
from mock import Mock, patch
|
from mock import Mock, patch
|
||||||
|
|
||||||
|
@ -736,3 +736,29 @@ def override_config(extra_config):
|
||||||
return func
|
return func
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
TV = TypeVar("TV")
|
||||||
|
|
||||||
|
|
||||||
|
def skip_unless(condition: bool, reason: str) -> Callable[[TV], TV]:
|
||||||
|
"""A test decorator which will skip the decorated test unless a condition is set
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
class MyTestCase(TestCase):
|
||||||
|
@skip_unless(HAS_FOO, "Cannot test without foo")
|
||||||
|
def test_foo(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
Args:
|
||||||
|
condition: If true, the test will be skipped
|
||||||
|
reason: the reason to give for skipping the test
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(f: TV) -> TV:
|
||||||
|
if not condition:
|
||||||
|
f.skip = reason # type: ignore
|
||||||
|
return f
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
Loading…
Reference in New Issue