view tests/unit/test_plugin_xep_0082.py @ 3888:aa7197b67c26

component AP gateway: AP <=> XMPP reactions conversions: - Pubsub Attachments plugin has been renamed to XEP-0470 following publication - XEP-0470 has been updated to follow 0.2 changes - AP reactions (as implemented in Pleroma) are converted to XEP-0470 - XEP-0470 events are converted to AP reactions (again, using "EmojiReact" from Pleroma) - AP activities related to attachments (like/reactions) are cached in Libervia because it's not possible to retrieve them from Pleroma instances once they have been emitted (doing an HTTP get on their ID returns a 404). For now those cache are not flushed, this should be improved in the future. - `sharedInbox` is used when available. Pleroma returns a 500 HTTP error when ``to`` or ``cc`` are used in a direct inbox. - reactions and like are not currently used for direct messages, because they can't be emitted from Pleroma in this case, thus there is no point in implementing them for the moment. rel 371
author Goffi <goffi@goffi.org>
date Wed, 31 Aug 2022 17:07:03 +0200
parents 00212260f659
children 8289ac1b34f4
line wrap: on
line source

#!/usr/bin/env python3

# Tests for Libervia's XMPP Date and Time Profile formatting and parsing plugin
# Copyright (C) 2022-2022 Tim Henkes (me@syndace.dev)

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Type-check with `mypy --strict`
# Lint with `pylint`

from datetime import date, datetime, time, timezone

import pytest

from sat.plugins.plugin_xep_0082 import XEP_0082


__all__ = [  # pylint: disable=unused-variable
    "test_date_formatting",
    "test_date_parsing",
    "test_datetime_formatting",
    "test_datetime_parsing",
    "test_time_formatting",
    "test_time_parsing"
]


def test_date_formatting() -> None:  # pylint: disable=missing-function-docstring
    # The following tests don't check the output of format_date directly; instead, they
    # assume that parse_date rejects incorrect formatting.

    # The date version 0.1 of XEP-0082 was published
    value = date(2003, 4, 21)

    # Check that the parsed date equals the formatted date
    assert XEP_0082.parse_date(XEP_0082.format_date(value)) == value

    # Check that a date instance is returned when format_date is called without an
    # explicit input date
    assert isinstance(XEP_0082.parse_date(XEP_0082.format_date()), date)


def test_date_parsing() -> None:  # pylint: disable=missing-function-docstring
    # There isn't really a point in testing much more than this
    assert XEP_0082.parse_date("2003-04-21") == date(2003, 4, 21)


def test_datetime_formatting() -> None:  # pylint: disable=missing-function-docstring
    # The following tests don't check the output of format_datetime directly; instead,
    # they assume that parse_datetime rejects incorrect formatting.

    # A datetime in UTC
    value = datetime(1234, 5, 6, 7, 8, 9, 123456, timezone.utc)

    # Check that the parsed datetime equals the formatted datetime except for the
    # microseconds
    parsed = XEP_0082.parse_datetime(XEP_0082.format_datetime(value))
    assert parsed != value
    assert parsed.replace(microsecond=123456) == value

    # Check that the parsed datetime equals the formatted datetime including microseconds
    assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value, True)) == value

    # A datetime in some other timezone, from the Python docs of the datetime module
    value = datetime.fromisoformat("2011-11-04T00:05:23+04:00")

    # Check that the parsed datetime equals the formatted datetime with or without
    # microseconds
    assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value)) == value
    assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value, True)) == value

    # Check that the datetime was converted to UTC while formatting
    assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value)).tzinfo == timezone.utc

    # Check that a datetime instance is returned when format_datetime is called without an
    # explicit input
    # datetime
    assert isinstance(XEP_0082.parse_datetime(XEP_0082.format_datetime()), datetime)
    assert isinstance(XEP_0082.parse_datetime(XEP_0082.format_datetime(
        include_microsecond=True
    )), datetime)
    assert XEP_0082.parse_datetime(XEP_0082.format_datetime()).tzinfo == timezone.utc


def test_datetime_parsing() -> None:  # pylint: disable=missing-function-docstring
    # Datetime of the first human steps on the Moon (UTC)
    value = datetime(1969, 7, 21, 2, 56, 15, tzinfo=timezone.utc)

    # With timezone 'Z', without a fraction of a second
    assert XEP_0082.parse_datetime("1969-07-21T02:56:15Z") == value

    # With timezone '+04:00', without a fraction of a second
    assert XEP_0082.parse_datetime("1969-07-21T06:56:15+04:00") == value

    # With timezone '-05:00', without a fraction of a second
    assert XEP_0082.parse_datetime("1969-07-20T21:56:15-05:00") == value

    # Without timezone, without a fraction of a second
    with pytest.raises(ValueError):
        XEP_0082.parse_datetime("1969-07-21T02:56:15")

    # With timezone 'Z', with a fraction of a second consisting of two digits
    assert XEP_0082.parse_datetime("1969-07-21T02:56:15.12Z") == \
        value.replace(microsecond=120000)

    # With timezone 'Z', with a fraction of a second consisting of nine digits
    assert XEP_0082.parse_datetime("1969-07-21T02:56:15.123456789Z") == \
        value.replace(microsecond=123456)

    # With timezone '+04:00', with a fraction of a second consisting of six digits
    assert XEP_0082.parse_datetime("1969-07-21T06:56:15.123456+04:00") == \
        value.replace(microsecond=123456)

    # With timezone '-05:00', with a fraction of a second consisting of zero digits
    assert XEP_0082.parse_datetime("1969-07-20T21:56:15.-05:00") == value

    # Without timezone, with a fraction of a second consisting of six digits
    with pytest.raises(ValueError):
        XEP_0082.parse_datetime("1969-07-21T02:56:15.123456")


def test_time_formatting() -> None:  # pylint: disable=missing-function-docstring
    # The following tests don't check the output of format_time directly; instead, they
    # assume that parse_time rejects incorrect formatting.

    # A time in UTC
    value = time(12, 34, 56, 789012, timezone.utc)

    # Check that the parsed time equals the formatted time except for the microseconds
    parsed = XEP_0082.parse_time(XEP_0082.format_time(value))
    assert parsed != value
    assert parsed.replace(microsecond=789012) == value

    # Check that the parsed time equals the formatted time including microseconds
    assert XEP_0082.parse_time(XEP_0082.format_time(value, True)) == value

    # A time in some other timezone, from the Python docs of the datetime module
    value = time.fromisoformat("04:23:01+04:00")

    # Check that the parsed time equals the formatted time with or without microseconds
    assert XEP_0082.parse_time(XEP_0082.format_time(value)) == value
    assert XEP_0082.parse_time(XEP_0082.format_time(value, True)) == value

    # Check that the time has retained its timezone
    assert XEP_0082.parse_time(XEP_0082.format_time(value)).tzinfo == value.tzinfo

    # A time without timezone information, from the Python docs of the datetime module
    value = time.fromisoformat("04:23:01")

    # Check that the parsed time doesn't have timezone information either
    assert XEP_0082.parse_time(XEP_0082.format_time(value)).tzinfo is None

    # Check that a time instance is returned when format_time is called without an
    # explicit input date
    assert isinstance(XEP_0082.parse_time(XEP_0082.format_time()), time)
    assert isinstance(XEP_0082.parse_time(XEP_0082.format_time(
        include_microsecond=True
    )), time)
    assert XEP_0082.parse_time(XEP_0082.format_time()).tzinfo == timezone.utc


def test_time_parsing() -> None:  # pylint: disable=missing-function-docstring
    # Time for tea
    value = time(16, 0, 0, tzinfo=timezone.utc)

    # With timezone 'Z', without a fraction of a second
    assert XEP_0082.parse_time("16:00:00Z") == value

    # With timezone '+04:00', without a fraction of a second
    assert XEP_0082.parse_time("20:00:00+04:00") == value

    # With timezone '-05:00', without a fraction of a second
    assert XEP_0082.parse_time("11:00:00-05:00") == value

    # Without a timezone, without a fraction of a second
    assert XEP_0082.parse_time("16:00:00") == value.replace(tzinfo=None)

    # With timezone 'Z', with a fraction of a second consisting of two digits
    assert XEP_0082.parse_time("16:00:00.12Z") == value.replace(microsecond=120000)

    # With timezone 'Z', with a fraction of a second consisting of nine digits
    assert XEP_0082.parse_time("16:00:00.123456789Z") == value.replace(microsecond=123456)

    # With timezone '+04:00', with a fraction of a second consisting of six digits
    assert XEP_0082.parse_time("20:00:00.123456+04:00") == \
        value.replace(microsecond=123456)

    # With timezone '-05:00', with a fraction of a second consisting of zero digits
    assert XEP_0082.parse_time("11:00:00.-05:00") == value

    # Without a timezone, with a fraction of a second consisting of six digits
    assert XEP_0082.parse_time("16:00:00.123456") == \
        value.replace(microsecond=123456, tzinfo=None)