Add missing type hints for tests.events. (#14904)

This commit is contained in:
Patrick Cloke 2023-01-25 15:14:03 -05:00 committed by GitHub
parent 8bc5d1406c
commit 3c3ba31507
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 64 deletions

1
changelog.d/14904.misc Normal file
View file

@ -0,0 +1 @@
Add missing type hints.

View file

@ -35,8 +35,6 @@ exclude = (?x)
|tests/api/test_auth.py |tests/api/test_auth.py
|tests/app/test_openid_listener.py |tests/app/test_openid_listener.py
|tests/appservice/test_scheduler.py |tests/appservice/test_scheduler.py
|tests/events/test_presence_router.py
|tests/events/test_utils.py
|tests/federation/test_federation_catch_up.py |tests/federation/test_federation_catch_up.py
|tests/federation/test_federation_sender.py |tests/federation/test_federation_sender.py
|tests/handlers/test_typing.py |tests/handlers/test_typing.py
@ -86,6 +84,9 @@ disallow_untyped_defs = True
[mypy-tests.crypto.*] [mypy-tests.crypto.*]
disallow_untyped_defs = True disallow_untyped_defs = True
[mypy-tests.events.*]
disallow_untyped_defs = True
[mypy-tests.federation.transport.test_client] [mypy-tests.federation.transport.test_client]
disallow_untyped_defs = True disallow_untyped_defs = True

View file

@ -605,10 +605,11 @@ class EventClientSerializer:
_PowerLevel = Union[str, int] _PowerLevel = Union[str, int]
PowerLevelsContent = Mapping[str, Union[_PowerLevel, Mapping[str, _PowerLevel]]]
def copy_and_fixup_power_levels_contents( def copy_and_fixup_power_levels_contents(
old_power_levels: Mapping[str, Union[_PowerLevel, Mapping[str, _PowerLevel]]] old_power_levels: PowerLevelsContent,
) -> Dict[str, Union[int, Dict[str, int]]]: ) -> Dict[str, Union[int, Dict[str, int]]]:
"""Copy the content of a power_levels event, unfreezing frozendicts along the way. """Copy the content of a power_levels event, unfreezing frozendicts along the way.

View file

@ -16,6 +16,8 @@ from unittest.mock import Mock
import attr import attr
from twisted.test.proto_helpers import MemoryReactor
from synapse.api.constants import EduTypes from synapse.api.constants import EduTypes
from synapse.events.presence_router import PresenceRouter, load_legacy_presence_router from synapse.events.presence_router import PresenceRouter, load_legacy_presence_router
from synapse.federation.units import Transaction from synapse.federation.units import Transaction
@ -23,11 +25,13 @@ from synapse.handlers.presence import UserPresenceState
from synapse.module_api import ModuleApi from synapse.module_api import ModuleApi
from synapse.rest import admin from synapse.rest import admin
from synapse.rest.client import login, presence, room from synapse.rest.client import login, presence, room
from synapse.server import HomeServer
from synapse.types import JsonDict, StreamToken, create_requester from synapse.types import JsonDict, StreamToken, create_requester
from synapse.util import Clock
from tests.handlers.test_sync import generate_sync_config from tests.handlers.test_sync import generate_sync_config
from tests.test_utils import simple_async_mock from tests.test_utils import simple_async_mock
from tests.unittest import FederatingHomeserverTestCase, TestCase, override_config from tests.unittest import FederatingHomeserverTestCase, override_config
@attr.s @attr.s
@ -49,9 +53,7 @@ class LegacyPresenceRouterTestModule:
} }
return users_to_state return users_to_state
async def get_interested_users( async def get_interested_users(self, user_id: str) -> Union[Set[str], str]:
self, user_id: str
) -> Union[Set[str], PresenceRouter.ALL_USERS]:
if user_id in self._config.users_who_should_receive_all_presence: if user_id in self._config.users_who_should_receive_all_presence:
return PresenceRouter.ALL_USERS return PresenceRouter.ALL_USERS
@ -71,9 +73,14 @@ class LegacyPresenceRouterTestModule:
# Initialise a typed config object # Initialise a typed config object
config = PresenceRouterTestConfig() config = PresenceRouterTestConfig()
config.users_who_should_receive_all_presence = config_dict.get( users_who_should_receive_all_presence = config_dict.get(
"users_who_should_receive_all_presence" "users_who_should_receive_all_presence"
) )
assert isinstance(users_who_should_receive_all_presence, list)
config.users_who_should_receive_all_presence = (
users_who_should_receive_all_presence
)
return config return config
@ -96,9 +103,7 @@ class PresenceRouterTestModule:
} }
return users_to_state return users_to_state
async def get_interested_users( async def get_interested_users(self, user_id: str) -> Union[Set[str], str]:
self, user_id: str
) -> Union[Set[str], PresenceRouter.ALL_USERS]:
if user_id in self._config.users_who_should_receive_all_presence: if user_id in self._config.users_who_should_receive_all_presence:
return PresenceRouter.ALL_USERS return PresenceRouter.ALL_USERS
@ -118,9 +123,14 @@ class PresenceRouterTestModule:
# Initialise a typed config object # Initialise a typed config object
config = PresenceRouterTestConfig() config = PresenceRouterTestConfig()
config.users_who_should_receive_all_presence = config_dict.get( users_who_should_receive_all_presence = config_dict.get(
"users_who_should_receive_all_presence" "users_who_should_receive_all_presence"
) )
assert isinstance(users_who_should_receive_all_presence, list)
config.users_who_should_receive_all_presence = (
users_who_should_receive_all_presence
)
return config return config
@ -140,7 +150,7 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
presence.register_servlets, presence.register_servlets,
] ]
def make_homeserver(self, reactor, clock): def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
# Mock out the calls over federation. # Mock out the calls over federation.
fed_transport_client = Mock(spec=["send_transaction"]) fed_transport_client = Mock(spec=["send_transaction"])
fed_transport_client.send_transaction = simple_async_mock({}) fed_transport_client.send_transaction = simple_async_mock({})
@ -153,7 +163,9 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
return hs return hs
def prepare(self, reactor, clock, homeserver): def prepare(
self, reactor: MemoryReactor, clock: Clock, homeserver: HomeServer
) -> None:
self.sync_handler = self.hs.get_sync_handler() self.sync_handler = self.hs.get_sync_handler()
self.module_api = homeserver.get_module_api() self.module_api = homeserver.get_module_api()
@ -176,7 +188,7 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
}, },
} }
) )
def test_receiving_all_presence_legacy(self): def test_receiving_all_presence_legacy(self) -> None:
self.receiving_all_presence_test_body() self.receiving_all_presence_test_body()
@override_config( @override_config(
@ -193,10 +205,10 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
], ],
} }
) )
def test_receiving_all_presence(self): def test_receiving_all_presence(self) -> None:
self.receiving_all_presence_test_body() self.receiving_all_presence_test_body()
def receiving_all_presence_test_body(self): def receiving_all_presence_test_body(self) -> None:
"""Test that a user that does not share a room with another other can receive """Test that a user that does not share a room with another other can receive
presence for them, due to presence routing. presence for them, due to presence routing.
""" """
@ -302,7 +314,7 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
}, },
} }
) )
def test_send_local_online_presence_to_with_module_legacy(self): def test_send_local_online_presence_to_with_module_legacy(self) -> None:
self.send_local_online_presence_to_with_module_test_body() self.send_local_online_presence_to_with_module_test_body()
@override_config( @override_config(
@ -321,10 +333,10 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
], ],
} }
) )
def test_send_local_online_presence_to_with_module(self): def test_send_local_online_presence_to_with_module(self) -> None:
self.send_local_online_presence_to_with_module_test_body() self.send_local_online_presence_to_with_module_test_body()
def send_local_online_presence_to_with_module_test_body(self): def send_local_online_presence_to_with_module_test_body(self) -> None:
"""Tests that send_local_presence_to_users sends local online presence to a set """Tests that send_local_presence_to_users sends local online presence to a set
of specified local and remote users, with a custom PresenceRouter module enabled. of specified local and remote users, with a custom PresenceRouter module enabled.
""" """
@ -447,18 +459,18 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
continue continue
# EDUs can contain multiple presence updates # EDUs can contain multiple presence updates
for presence_update in edu["content"]["push"]: for presence_edu in edu["content"]["push"]:
# Check for presence updates that contain the user IDs we're after # Check for presence updates that contain the user IDs we're after
found_users.add(presence_update["user_id"]) found_users.add(presence_edu["user_id"])
# Ensure that no offline states are being sent out # Ensure that no offline states are being sent out
self.assertNotEqual(presence_update["presence"], "offline") self.assertNotEqual(presence_edu["presence"], "offline")
self.assertEqual(found_users, expected_users) self.assertEqual(found_users, expected_users)
def send_presence_update( def send_presence_update(
testcase: TestCase, testcase: FederatingHomeserverTestCase,
user_id: str, user_id: str,
access_token: str, access_token: str,
presence_state: str, presence_state: str,
@ -479,7 +491,7 @@ def send_presence_update(
def sync_presence( def sync_presence(
testcase: TestCase, testcase: FederatingHomeserverTestCase,
user_id: str, user_id: str,
since_token: Optional[StreamToken] = None, since_token: Optional[StreamToken] = None,
) -> Tuple[List[UserPresenceState], StreamToken]: ) -> Tuple[List[UserPresenceState], StreamToken]:
@ -500,7 +512,7 @@ def sync_presence(
requester = create_requester(user_id) requester = create_requester(user_id)
sync_config = generate_sync_config(requester.user.to_string()) sync_config = generate_sync_config(requester.user.to_string())
sync_result = testcase.get_success( sync_result = testcase.get_success(
testcase.sync_handler.wait_for_sync_for_user( testcase.hs.get_sync_handler().wait_for_sync_for_user(
requester, sync_config, since_token requester, sync_config, since_token
) )
) )

View file

@ -12,9 +12,14 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from twisted.test.proto_helpers import MemoryReactor
from synapse.events import EventBase
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.rest import admin from synapse.rest import admin
from synapse.rest.client import login, room from synapse.rest.client import login, room
from synapse.server import HomeServer
from synapse.util import Clock
from tests import unittest from tests import unittest
from tests.test_utils.event_injection import create_event from tests.test_utils.event_injection import create_event
@ -27,7 +32,7 @@ class TestEventContext(unittest.HomeserverTestCase):
room.register_servlets, room.register_servlets,
] ]
def prepare(self, reactor, clock, hs): def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
self.store = hs.get_datastores().main self.store = hs.get_datastores().main
self._storage_controllers = hs.get_storage_controllers() self._storage_controllers = hs.get_storage_controllers()
@ -35,7 +40,7 @@ class TestEventContext(unittest.HomeserverTestCase):
self.user_tok = self.login("u1", "pass") self.user_tok = self.login("u1", "pass")
self.room_id = self.helper.create_room_as(tok=self.user_tok) self.room_id = self.helper.create_room_as(tok=self.user_tok)
def test_serialize_deserialize_msg(self): def test_serialize_deserialize_msg(self) -> None:
"""Test that an EventContext for a message event is the same after """Test that an EventContext for a message event is the same after
serialize/deserialize. serialize/deserialize.
""" """
@ -51,7 +56,7 @@ class TestEventContext(unittest.HomeserverTestCase):
self._check_serialize_deserialize(event, context) self._check_serialize_deserialize(event, context)
def test_serialize_deserialize_state_no_prev(self): def test_serialize_deserialize_state_no_prev(self) -> None:
"""Test that an EventContext for a state event (with not previous entry) """Test that an EventContext for a state event (with not previous entry)
is the same after serialize/deserialize. is the same after serialize/deserialize.
""" """
@ -67,7 +72,7 @@ class TestEventContext(unittest.HomeserverTestCase):
self._check_serialize_deserialize(event, context) self._check_serialize_deserialize(event, context)
def test_serialize_deserialize_state_prev(self): def test_serialize_deserialize_state_prev(self) -> None:
"""Test that an EventContext for a state event (which replaces a """Test that an EventContext for a state event (which replaces a
previous entry) is the same after serialize/deserialize. previous entry) is the same after serialize/deserialize.
""" """
@ -84,7 +89,9 @@ class TestEventContext(unittest.HomeserverTestCase):
self._check_serialize_deserialize(event, context) self._check_serialize_deserialize(event, context)
def _check_serialize_deserialize(self, event, context): def _check_serialize_deserialize(
self, event: EventBase, context: EventContext
) -> None:
serialized = self.get_success(context.serialize(event, self.store)) serialized = self.get_success(context.serialize(event, self.store))
d_context = EventContext.deserialize(self._storage_controllers, serialized) d_context = EventContext.deserialize(self._storage_controllers, serialized)

View file

@ -13,21 +13,24 @@
# limitations under the License. # limitations under the License.
import unittest as stdlib_unittest import unittest as stdlib_unittest
from typing import Any, List, Mapping, Optional
from synapse.api.constants import EventContentFields from synapse.api.constants import EventContentFields
from synapse.api.room_versions import RoomVersions from synapse.api.room_versions import RoomVersions
from synapse.events import make_event_from_dict from synapse.events import EventBase, make_event_from_dict
from synapse.events.utils import ( from synapse.events.utils import (
PowerLevelsContent,
SerializeEventConfig, SerializeEventConfig,
copy_and_fixup_power_levels_contents, copy_and_fixup_power_levels_contents,
maybe_upsert_event_field, maybe_upsert_event_field,
prune_event, prune_event,
serialize_event, serialize_event,
) )
from synapse.types import JsonDict
from synapse.util.frozenutils import freeze from synapse.util.frozenutils import freeze
def MockEvent(**kwargs): def MockEvent(**kwargs: Any) -> EventBase:
if "event_id" not in kwargs: if "event_id" not in kwargs:
kwargs["event_id"] = "fake_event_id" kwargs["event_id"] = "fake_event_id"
if "type" not in kwargs: if "type" not in kwargs:
@ -60,7 +63,7 @@ class TestMaybeUpsertEventField(stdlib_unittest.TestCase):
class PruneEventTestCase(stdlib_unittest.TestCase): class PruneEventTestCase(stdlib_unittest.TestCase):
def run_test(self, evdict, matchdict, **kwargs): def run_test(self, evdict: JsonDict, matchdict: JsonDict, **kwargs: Any) -> None:
""" """
Asserts that a new event constructed with `evdict` will look like Asserts that a new event constructed with `evdict` will look like
`matchdict` when it is redacted. `matchdict` when it is redacted.
@ -74,7 +77,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
prune_event(make_event_from_dict(evdict, **kwargs)).get_dict(), matchdict prune_event(make_event_from_dict(evdict, **kwargs)).get_dict(), matchdict
) )
def test_minimal(self): def test_minimal(self) -> None:
self.run_test( self.run_test(
{"type": "A", "event_id": "$test:domain"}, {"type": "A", "event_id": "$test:domain"},
{ {
@ -86,7 +89,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
}, },
) )
def test_basic_keys(self): def test_basic_keys(self) -> None:
"""Ensure that the keys that should be untouched are kept.""" """Ensure that the keys that should be untouched are kept."""
# Note that some of the values below don't really make sense, but the # Note that some of the values below don't really make sense, but the
# pruning of events doesn't worry about the values of any fields (with # pruning of events doesn't worry about the values of any fields (with
@ -138,7 +141,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
room_version=RoomVersions.MSC2176, room_version=RoomVersions.MSC2176,
) )
def test_unsigned(self): def test_unsigned(self) -> None:
"""Ensure that unsigned properties get stripped (except age_ts and replaces_state).""" """Ensure that unsigned properties get stripped (except age_ts and replaces_state)."""
self.run_test( self.run_test(
{ {
@ -159,7 +162,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
}, },
) )
def test_content(self): def test_content(self) -> None:
"""The content dictionary should be stripped in most cases.""" """The content dictionary should be stripped in most cases."""
self.run_test( self.run_test(
{"type": "C", "event_id": "$test:domain", "content": {"things": "here"}}, {"type": "C", "event_id": "$test:domain", "content": {"things": "here"}},
@ -194,7 +197,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
}, },
) )
def test_create(self): def test_create(self) -> None:
"""Create events are partially redacted until MSC2176.""" """Create events are partially redacted until MSC2176."""
self.run_test( self.run_test(
{ {
@ -223,7 +226,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
room_version=RoomVersions.MSC2176, room_version=RoomVersions.MSC2176,
) )
def test_power_levels(self): def test_power_levels(self) -> None:
"""Power level events keep a variety of content keys.""" """Power level events keep a variety of content keys."""
self.run_test( self.run_test(
{ {
@ -273,7 +276,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
room_version=RoomVersions.MSC2176, room_version=RoomVersions.MSC2176,
) )
def test_alias_event(self): def test_alias_event(self) -> None:
"""Alias events have special behavior up through room version 6.""" """Alias events have special behavior up through room version 6."""
self.run_test( self.run_test(
{ {
@ -302,7 +305,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
room_version=RoomVersions.V6, room_version=RoomVersions.V6,
) )
def test_redacts(self): def test_redacts(self) -> None:
"""Redaction events have no special behaviour until MSC2174/MSC2176.""" """Redaction events have no special behaviour until MSC2174/MSC2176."""
self.run_test( self.run_test(
@ -328,7 +331,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
room_version=RoomVersions.MSC2176, room_version=RoomVersions.MSC2176,
) )
def test_join_rules(self): def test_join_rules(self) -> None:
"""Join rules events have changed behavior starting with MSC3083.""" """Join rules events have changed behavior starting with MSC3083."""
self.run_test( self.run_test(
{ {
@ -371,7 +374,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
room_version=RoomVersions.V8, room_version=RoomVersions.V8,
) )
def test_member(self): def test_member(self) -> None:
"""Member events have changed behavior starting with MSC3375.""" """Member events have changed behavior starting with MSC3375."""
self.run_test( self.run_test(
{ {
@ -417,12 +420,12 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
class SerializeEventTestCase(stdlib_unittest.TestCase): class SerializeEventTestCase(stdlib_unittest.TestCase):
def serialize(self, ev, fields): def serialize(self, ev: EventBase, fields: Optional[List[str]]) -> JsonDict:
return serialize_event( return serialize_event(
ev, 1479807801915, config=SerializeEventConfig(only_event_fields=fields) ev, 1479807801915, config=SerializeEventConfig(only_event_fields=fields)
) )
def test_event_fields_works_with_keys(self): def test_event_fields_works_with_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent(sender="@alice:localhost", room_id="!foo:bar"), ["room_id"] MockEvent(sender="@alice:localhost", room_id="!foo:bar"), ["room_id"]
@ -430,7 +433,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{"room_id": "!foo:bar"}, {"room_id": "!foo:bar"},
) )
def test_event_fields_works_with_nested_keys(self): def test_event_fields_works_with_nested_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -443,7 +446,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{"content": {"body": "A message"}}, {"content": {"body": "A message"}},
) )
def test_event_fields_works_with_dot_keys(self): def test_event_fields_works_with_dot_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -456,7 +459,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{"content": {"key.with.dots": {}}}, {"content": {"key.with.dots": {}}},
) )
def test_event_fields_works_with_nested_dot_keys(self): def test_event_fields_works_with_nested_dot_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -472,7 +475,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{"content": {"nested.dot.key": {"leaf.key": 42}}}, {"content": {"nested.dot.key": {"leaf.key": 42}}},
) )
def test_event_fields_nops_with_unknown_keys(self): def test_event_fields_nops_with_unknown_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -485,7 +488,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{"content": {"foo": "bar"}}, {"content": {"foo": "bar"}},
) )
def test_event_fields_nops_with_non_dict_keys(self): def test_event_fields_nops_with_non_dict_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -498,7 +501,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{}, {},
) )
def test_event_fields_nops_with_array_keys(self): def test_event_fields_nops_with_array_keys(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -511,7 +514,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
{}, {},
) )
def test_event_fields_all_fields_if_empty(self): def test_event_fields_all_fields_if_empty(self) -> None:
self.assertEqual( self.assertEqual(
self.serialize( self.serialize(
MockEvent( MockEvent(
@ -531,16 +534,16 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
}, },
) )
def test_event_fields_fail_if_fields_not_str(self): def test_event_fields_fail_if_fields_not_str(self) -> None:
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
self.serialize( self.serialize(
MockEvent(room_id="!foo:bar", content={"foo": "bar"}), ["room_id", 4] MockEvent(room_id="!foo:bar", content={"foo": "bar"}), ["room_id", 4] # type: ignore[list-item]
) )
class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase): class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.test_content = { self.test_content: PowerLevelsContent = {
"ban": 50, "ban": 50,
"events": {"m.room.name": 100, "m.room.power_levels": 100}, "events": {"m.room.name": 100, "m.room.power_levels": 100},
"events_default": 0, "events_default": 0,
@ -553,10 +556,11 @@ class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
"users_default": 0, "users_default": 0,
} }
def _test(self, input): def _test(self, input: PowerLevelsContent) -> None:
a = copy_and_fixup_power_levels_contents(input) a = copy_and_fixup_power_levels_contents(input)
self.assertEqual(a["ban"], 50) self.assertEqual(a["ban"], 50)
assert isinstance(a["events"], Mapping)
self.assertEqual(a["events"]["m.room.name"], 100) self.assertEqual(a["events"]["m.room.name"], 100)
# make sure that changing the copy changes the copy and not the orig # make sure that changing the copy changes the copy and not the orig
@ -564,18 +568,19 @@ class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
a["events"]["m.room.power_levels"] = 20 a["events"]["m.room.power_levels"] = 20
self.assertEqual(input["ban"], 50) self.assertEqual(input["ban"], 50)
assert isinstance(input["events"], Mapping)
self.assertEqual(input["events"]["m.room.power_levels"], 100) self.assertEqual(input["events"]["m.room.power_levels"], 100)
def test_unfrozen(self): def test_unfrozen(self) -> None:
self._test(self.test_content) self._test(self.test_content)
def test_frozen(self): def test_frozen(self) -> None:
input = freeze(self.test_content) input = freeze(self.test_content)
self._test(input) self._test(input)
def test_stringy_integers(self): def test_stringy_integers(self) -> None:
"""String representations of decimal integers are converted to integers.""" """String representations of decimal integers are converted to integers."""
input = { input: PowerLevelsContent = {
"a": "100", "a": "100",
"b": { "b": {
"foo": 99, "foo": 99,
@ -603,9 +608,9 @@ class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
def test_invalid_types_raise_type_error(self) -> None: def test_invalid_types_raise_type_error(self) -> None:
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
copy_and_fixup_power_levels_contents({"a": ["hello", "grandma"]}) # type: ignore[arg-type] copy_and_fixup_power_levels_contents({"a": ["hello", "grandma"]}) # type: ignore[dict-item]
copy_and_fixup_power_levels_contents({"a": None}) # type: ignore[arg-type] copy_and_fixup_power_levels_contents({"a": None}) # type: ignore[dict-item]
def test_invalid_nesting_raises_type_error(self) -> None: def test_invalid_nesting_raises_type_error(self) -> None:
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
copy_and_fixup_power_levels_contents({"a": {"b": {"c": 1}}}) copy_and_fixup_power_levels_contents({"a": {"b": {"c": 1}}}) # type: ignore[dict-item]