diff --git a/tools/check-node-fixtures b/tools/check-node-fixtures index 7fa1e63a6c..edf342df2c 100755 --- a/tools/check-node-fixtures +++ b/tools/check-node-fixtures @@ -42,10 +42,11 @@ os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.test_settings" django.setup() from zerver.lib import event_schema -from zerver.lib.data_types import ( # force vertical +from zerver.lib.data_types import ( DictType, EnumType, ListType, + NumberType, UnionType, make_checker, schema, @@ -150,7 +151,7 @@ def from_openapi(node: Dict[str, Any]) -> Any: return int if node["type"] == "number": - return float + return NumberType() if node["type"] == "string": if "enum" in node: diff --git a/zerver/lib/data_types.py b/zerver/lib/data_types.py index 0a143fdb42..af190a92eb 100644 --- a/zerver/lib/data_types.py +++ b/zerver/lib/data_types.py @@ -93,6 +93,16 @@ class Equals: return f"{var_name} in {repr([self.expected_value])}" +class NumberType: + def check_data(self, var_name: str, val: Optional[Any]) -> None: + if isinstance(val, int) or isinstance(val, float): + return + raise AssertionError(f"{var_name} is not a number") + + def schema(self, var_name: str) -> str: + return f"{var_name}: number" + + class ListType: def __init__(self, sub_type: Any, length: Optional[int] = None) -> None: self.sub_type = sub_type diff --git a/zerver/lib/event_schema.py b/zerver/lib/event_schema.py index 6a37f72faa..b628cfdcae 100644 --- a/zerver/lib/event_schema.py +++ b/zerver/lib/event_schema.py @@ -12,6 +12,7 @@ from zerver.lib.data_types import ( EnumType, Equals, ListType, + NumberType, OptionalType, UnionType, UrlType, @@ -166,6 +167,25 @@ default_streams_event = event_dict_type( ) check_default_streams = make_checker(default_streams_event) +_hotspot = DictType( + required_keys=[ + # force vertical + ("name", str), + ("title", str), + ("description", str), + ("delay", NumberType()), + ] +) + +hotspots_event = event_dict_type( + required_keys=[ + # force vertical + ("type", Equals("hotspots")), + ("hotspots", ListType(_hotspot),), + ] +) +check_hotspots = make_checker(hotspots_event) + invites_changed_event = event_dict_type( required_keys=[ # the most boring event...no metadata diff --git a/zerver/tests/test_data_types.py b/zerver/tests/test_data_types.py index 10c9a700e8..04765d74c9 100644 --- a/zerver/tests/test_data_types.py +++ b/zerver/tests/test_data_types.py @@ -3,6 +3,7 @@ from zerver.lib.data_types import ( EnumType, Equals, ListType, + NumberType, OptionalType, UnionType, UrlType, @@ -22,6 +23,7 @@ class MiscTest(ZulipTestCase): ("type", Equals("realm")), ("maybe_n", OptionalType(int)), ("s", str), + ("timestamp", NumberType()), ("flag", bool), ("level", EnumType([1, 2, 3])), ("lst", ListType(int)), @@ -37,6 +39,7 @@ test (dict): type: int maybe_n: int s: str + timestamp: number type in ['realm'] url: str value (union): diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 516e9ce1dd..3ccc9493ad 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -95,6 +95,7 @@ from zerver.lib.event_schema import ( check_default_stream_groups, check_default_streams, check_events_dict, + check_hotspots, check_invites_changed, check_message, check_reaction, @@ -1607,18 +1608,9 @@ class NormalActionsTest(BaseAction): self.user_profile.tutorial_status = UserProfile.TUTORIAL_WAITING self.user_profile.save(update_fields=['tutorial_status']) - schema_checker = check_events_dict([ - ('type', equals('hotspots')), - ('hotspots', check_list(check_dict_only([ - ('name', check_string), - ('title', check_string), - ('description', check_string), - ('delay', check_float), - ]))), - ]) events = self.verify_action( lambda: do_mark_hotspot_as_read(self.user_profile, 'intro_reply')) - schema_checker('events[0]', events[0]) + check_hotspots('events[0]', events[0]) def test_rename_stream(self) -> None: stream = self.make_stream('old_name')