kopia lustrzana https://github.com/collective/icalendar
Add CONFERENCE property
rodzic
3786498d29
commit
fc8872ddd8
|
@ -67,6 +67,9 @@ icalendar.prop
|
|||
.. automodule:: icalendar.prop
|
||||
:members:
|
||||
|
||||
.. automodule:: icalendar.prop.conference
|
||||
:members:
|
||||
|
||||
.. automodule:: icalendar.prop.image
|
||||
:members:
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ from icalendar.prop import (
|
|||
vUTCOffset,
|
||||
vWeekday,
|
||||
)
|
||||
from icalendar.prop.conference import Conference
|
||||
from icalendar.prop.image import Image
|
||||
|
||||
# Switching the timezone provider
|
||||
|
@ -104,6 +105,7 @@ __all__ = [
|
|||
"ComponentEndMissing",
|
||||
"ComponentFactory",
|
||||
"ComponentStartMissing",
|
||||
"Conference",
|
||||
"Event",
|
||||
"FeatureWillBeRemovedInFutureVersion",
|
||||
"FreeBusy",
|
||||
|
|
|
@ -9,7 +9,15 @@ from typing import TYPE_CHECKING, Optional, Sequence, Union
|
|||
from icalendar.enums import BUSYTYPE, CLASS, STATUS, TRANSP, StrEnum
|
||||
from icalendar.error import IncompleteComponent, InvalidCalendar
|
||||
from icalendar.parser_tools import SEQUENCE_TYPES
|
||||
from icalendar.prop import vCalAddress, vCategory, vDDDTypes, vDuration, vRecur, vText
|
||||
from icalendar.prop import (
|
||||
vCalAddress,
|
||||
vCategory,
|
||||
vDDDTypes,
|
||||
vDuration,
|
||||
vRecur,
|
||||
vText,
|
||||
)
|
||||
from icalendar.prop.conference import Conference
|
||||
from icalendar.prop.image import Image
|
||||
from icalendar.timezone import tzp
|
||||
from icalendar.tools import is_date
|
||||
|
@ -1617,6 +1625,113 @@ def _get_images(self: Component) -> list[Image]:
|
|||
|
||||
images_property = property(_get_images)
|
||||
|
||||
|
||||
def _get_conferences(self: Component) -> list[Conference]:
|
||||
"""Return the CONFERENCE properties as a list.
|
||||
|
||||
Purpose:
|
||||
This property specifies information for accessing a conferencing system.
|
||||
|
||||
Conformance:
|
||||
This property can be specified multiple times in a
|
||||
"VEVENT" or "VTODO" calendar component.
|
||||
|
||||
Description:
|
||||
This property specifies information for accessing a
|
||||
conferencing system for attendees of a meeting or task. This
|
||||
might be for a telephone-based conference number dial-in with
|
||||
access codes included (such as a tel: URI :rfc:`3966` or a sip: or
|
||||
sips: URI :rfc:`3261`), for a web-based video chat (such as an http:
|
||||
or https: URI :rfc:`7230`), or for an instant messaging group chat
|
||||
room (such as an xmpp: URI :rfc:`5122`). If a specific URI for a
|
||||
conferencing system is not available, a data: URI :rfc:`2397`
|
||||
containing a text description can be used.
|
||||
|
||||
A conference system can be a bidirectional communication channel
|
||||
or a uni-directional "broadcast feed".
|
||||
|
||||
The "FEATURE" property parameter is used to describe the key
|
||||
capabilities of the conference system to allow a client to choose
|
||||
the ones that give the required level of interaction from a set of
|
||||
multiple properties.
|
||||
|
||||
The "LABEL" property parameter is used to convey additional
|
||||
details on the use of the URI. For example, the URIs or access
|
||||
codes for the moderator and attendee of a teleconference system
|
||||
could be different, and the "LABEL" property parameter could be
|
||||
used to "tag" each "CONFERENCE" property to indicate which is
|
||||
which.
|
||||
|
||||
The "LANGUAGE" property parameter can be used to specify the
|
||||
language used for text values used with this property (as per
|
||||
Section 3.2.10 of :rfc:`5545`).
|
||||
|
||||
Example:
|
||||
The following are examples of this property:
|
||||
|
||||
.. code-block:: ical
|
||||
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE,MODERATOR;
|
||||
LABEL=Moderator dial-in:tel:+1-412-555-0123,,,654321
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE;
|
||||
LABEL=Attendee dial-in:tel:+1-412-555-0123,,,555123
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE;
|
||||
LABEL=Attendee dial-in:tel:+1-888-555-0456,,,555123
|
||||
CONFERENCE;VALUE=URI;FEATURE=CHAT;
|
||||
LABEL=Chat room:xmpp:chat-123@conference.example.com
|
||||
CONFERENCE;VALUE=URI;FEATURE=AUDIO,VIDEO;
|
||||
LABEL=Attendee dial-in:https://chat.example.com/audio?id=123456
|
||||
|
||||
Get all conferences:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from icalendar import Event
|
||||
>>> event = Event()
|
||||
>>> event.conferences
|
||||
[]
|
||||
|
||||
Set a conference:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from icalendar import Event, Conference
|
||||
>>> event = Event()
|
||||
>>> event.conferences = [
|
||||
... Conference(
|
||||
... "tel:+1-412-555-0123,,,654321",
|
||||
... feature="PHONE,MODERATOR",
|
||||
... label="Moderator dial-in",
|
||||
... language="EN",
|
||||
... )
|
||||
... ]
|
||||
>>> print(event.to_ical())
|
||||
BEGIN:VEVENT
|
||||
CONFERENCE;FEATURE="PHONE,MODERATOR";LABEL=Moderator dial-in;LANGUAGE=EN:t
|
||||
el:+1-412-555-0123,,,654321
|
||||
END:VEVENT
|
||||
|
||||
"""
|
||||
conferences = self.get("CONFERENCE", [])
|
||||
if not isinstance(conferences, Sequence):
|
||||
conferences = [conferences]
|
||||
return [Conference.from_uri(conference) for conference in conferences]
|
||||
|
||||
|
||||
def _set_conferences(self: Component, conferences: list[Conference] | None):
|
||||
"""Set the conferences."""
|
||||
_del_conferences(self)
|
||||
for conference in conferences or []:
|
||||
self.add("CONFERENCE", conference.to_uri())
|
||||
|
||||
|
||||
def _del_conferences(self: Component):
|
||||
"""Delete all conferences."""
|
||||
self.pop("CONFERENCE")
|
||||
|
||||
|
||||
conferences_property = property(_get_conferences, _set_conferences, _del_conferences)
|
||||
|
||||
__all__ = [
|
||||
"attendees_property",
|
||||
"busy_type_property",
|
||||
|
@ -1624,6 +1739,7 @@ __all__ = [
|
|||
"class_property",
|
||||
"color_property",
|
||||
"comments_property",
|
||||
"conferences_property",
|
||||
"contacts_property",
|
||||
"create_single_property",
|
||||
"description_property",
|
||||
|
|
|
@ -3,18 +3,20 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime, timezone
|
||||
from typing import ClassVar, Optional
|
||||
from typing import TYPE_CHECKING, ClassVar, Optional
|
||||
|
||||
from icalendar.attr import comments_property, single_utc_property, uid_property
|
||||
from icalendar.cal.component_factory import ComponentFactory
|
||||
from icalendar.caselessdict import CaselessDict
|
||||
from icalendar.compatibility import Self
|
||||
from icalendar.error import InvalidCalendar
|
||||
from icalendar.parser import Contentline, Contentlines, Parameters, q_join, q_split
|
||||
from icalendar.parser_tools import DEFAULT_ENCODING
|
||||
from icalendar.prop import TypesFactory, vDDDLists, vText
|
||||
from icalendar.timezone import tzp
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from icalendar.compatibility import Self
|
||||
|
||||
_marker = []
|
||||
|
||||
|
||||
|
@ -127,7 +129,13 @@ class Component(CaselessDict):
|
|||
obj.params[key] = item
|
||||
return obj
|
||||
|
||||
def add(self, name, value, parameters=None, encode=1):
|
||||
def add(
|
||||
self,
|
||||
name: str,
|
||||
value,
|
||||
parameters: dict[str, str] | Parameters = None,
|
||||
encode: bool = True, # noqa: FBT001
|
||||
):
|
||||
"""Add a property.
|
||||
|
||||
:param name: Name of the property.
|
||||
|
@ -293,7 +301,7 @@ class Component(CaselessDict):
|
|||
return properties
|
||||
|
||||
@classmethod
|
||||
def from_ical(cls, st, multiple:bool=False) -> Self|list[Self]:
|
||||
def from_ical(cls, st, multiple: bool = False) -> Self | list[Self]: # noqa: FBT001
|
||||
"""Populates the component recursively from a string."""
|
||||
stack = [] # a stack of components
|
||||
comps = []
|
||||
|
@ -560,7 +568,7 @@ class Component(CaselessDict):
|
|||
The property can be specified once in "VEVENT",
|
||||
"VTODO", or "VJOURNAL" calendar components. The value MUST be
|
||||
specified as a date with UTC time.
|
||||
|
||||
|
||||
""",
|
||||
)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ from icalendar.attr import (
|
|||
categories_property,
|
||||
class_property,
|
||||
color_property,
|
||||
conferences_property,
|
||||
contacts_property,
|
||||
create_single_property,
|
||||
description_property,
|
||||
|
@ -43,6 +44,7 @@ if TYPE_CHECKING:
|
|||
from icalendar.alarms import Alarms
|
||||
from icalendar.enums import CLASS, STATUS, TRANSP
|
||||
from icalendar.prop import vCalAddress
|
||||
from icalendar.prop.conference import Conference
|
||||
|
||||
|
||||
class Event(Component):
|
||||
|
@ -485,6 +487,7 @@ class Event(Component):
|
|||
status = status_property
|
||||
attendees = attendees_property
|
||||
images = images_property
|
||||
conferences = conferences_property
|
||||
|
||||
@classmethod
|
||||
def new(
|
||||
|
@ -495,6 +498,7 @@ class Event(Component):
|
|||
classification: CLASS | None = None,
|
||||
color: str | None = None,
|
||||
comments: list[str] | str | None = None,
|
||||
conferences: list[Conference] | None = None,
|
||||
contacts: list[str] | str | None = None,
|
||||
created: date | None = None,
|
||||
description: str | None = None,
|
||||
|
@ -522,6 +526,7 @@ class Event(Component):
|
|||
classification: The :attr:`classification` of the event.
|
||||
color: The :attr:`color` of the event.
|
||||
comments: The :attr:`Component.comments` of the event.
|
||||
conferences: The :attr:`conferences` of the event.
|
||||
created: The :attr:`Component.created` of the event.
|
||||
description: The :attr:`description` of the event.
|
||||
end: The :attr:`end` of the event.
|
||||
|
@ -571,6 +576,7 @@ class Event(Component):
|
|||
event.contacts = contacts
|
||||
event.status = status
|
||||
event.attendees = attendees
|
||||
event.conferences = conferences
|
||||
if cls._validate_new:
|
||||
cls._validate_start_and_end(start, end)
|
||||
return event
|
||||
|
|
|
@ -13,6 +13,7 @@ from icalendar.attr import (
|
|||
categories_property,
|
||||
class_property,
|
||||
color_property,
|
||||
conferences_property,
|
||||
contacts_property,
|
||||
create_single_property,
|
||||
description_property,
|
||||
|
@ -41,6 +42,7 @@ if TYPE_CHECKING:
|
|||
from icalendar.alarms import Alarms
|
||||
from icalendar.enums import CLASS, STATUS
|
||||
from icalendar.prop import vCalAddress
|
||||
from icalendar.prop.conference import Conference
|
||||
|
||||
|
||||
class Todo(Component):
|
||||
|
@ -353,6 +355,7 @@ class Todo(Component):
|
|||
status = status_property
|
||||
attendees = attendees_property
|
||||
images = images_property
|
||||
conferences = conferences_property
|
||||
|
||||
@classmethod
|
||||
def new(
|
||||
|
@ -364,6 +367,7 @@ class Todo(Component):
|
|||
color: str | None = None,
|
||||
comments: list[str] | str | None = None,
|
||||
contacts: list[str] | str | None = None,
|
||||
conferences: list[Conference] | None = None,
|
||||
created: date | None = None,
|
||||
description: str | None = None,
|
||||
end: date | datetime | None = None,
|
||||
|
@ -389,6 +393,7 @@ class Todo(Component):
|
|||
classification: The :attr:`classification` of the todo.
|
||||
color: The :attr:`color` of the todo.
|
||||
comments: The :attr:`Component.comments` of the todo.
|
||||
conferences: The :attr:`conferences` if the todo.
|
||||
created: The :attr:`Component.created` of the todo.
|
||||
description: The :attr:`description` of the todo.
|
||||
end: The :attr:`end` of the todo.
|
||||
|
@ -435,6 +440,7 @@ class Todo(Component):
|
|||
todo.contacts = contacts
|
||||
todo.status = status
|
||||
todo.attendees = attendees
|
||||
todo.conferences = conferences
|
||||
if cls._validate_new:
|
||||
cls._validate_start_and_end(start, end)
|
||||
return todo
|
||||
|
|
|
@ -1769,8 +1769,8 @@ class vUri(str):
|
|||
|
||||
def __new__(
|
||||
cls,
|
||||
value,
|
||||
encoding=DEFAULT_ENCODING,
|
||||
value: str,
|
||||
encoding: str = DEFAULT_ENCODING,
|
||||
/,
|
||||
params: Optional[dict[str, Any]] = None,
|
||||
):
|
||||
|
@ -2145,6 +2145,7 @@ class TypesFactory(CaselessDict):
|
|||
"recurrence-id": "date-time",
|
||||
"related-to": "text",
|
||||
"url": "uri",
|
||||
"conference": "uri", # RFC 7986
|
||||
"source": "uri",
|
||||
"uid": "text",
|
||||
# Recurrence Component Properties
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
"""Conferences according to Section 5.11 of :rfc:`7986`."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from icalendar.prop import vUri
|
||||
|
||||
|
||||
@dataclass
|
||||
class Conference:
|
||||
"""Conferences according to Section 5.11 of :rfc:`7986`.
|
||||
|
||||
Purpose:
|
||||
Information for accessing a conferencing system.
|
||||
|
||||
Conformance:
|
||||
This property can be specified multiple times in a
|
||||
"VEVENT" or "VTODO" calendar component.
|
||||
|
||||
Description:
|
||||
This property specifies information for accessing a
|
||||
conferencing system for attendees of a meeting or task. This
|
||||
might be for a telephone-based conference number dial-in with
|
||||
access codes included (such as a tel: URI :rfc:`3966` or a sip: or
|
||||
sips: URI :rfc:`3261`), for a web-based video chat (such as an http:
|
||||
or https: URI :rfc:`7230`), or for an instant messaging group chat
|
||||
room (such as an xmpp: URI :rfc:`5122`). If a specific URI for a
|
||||
conferencing system is not available, a data: URI :rfc:`2397`
|
||||
containing a text description can be used.
|
||||
|
||||
A conference system can be a bidirectional communication channel
|
||||
or a uni-directional "broadcast feed".
|
||||
|
||||
The "FEATURE" property parameter is used to describe the key
|
||||
capabilities of the conference system to allow a client to choose
|
||||
the ones that give the required level of interaction from a set of
|
||||
multiple properties.
|
||||
|
||||
The "LABEL" property parameter is used to convey additional
|
||||
details on the use of the URI. For example, the URIs or access
|
||||
codes for the moderator and attendee of a teleconference system
|
||||
could be different, and the "LABEL" property parameter could be
|
||||
used to "tag" each "CONFERENCE" property to indicate which is
|
||||
which.
|
||||
|
||||
The "LANGUAGE" property parameter can be used to specify the
|
||||
language used for text values used with this property (as per
|
||||
Section 3.2.10 of :rfc:`5545`).
|
||||
|
||||
Example:
|
||||
The following are examples of this property:
|
||||
|
||||
.. code-block:: ical
|
||||
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE,MODERATOR;
|
||||
LABEL=Moderator dial-in:tel:+1-412-555-0123,,,654321
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE;
|
||||
LABEL=Attendee dial-in:tel:+1-412-555-0123,,,555123
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE;
|
||||
LABEL=Attendee dial-in:tel:+1-888-555-0456,,,555123
|
||||
CONFERENCE;VALUE=URI;FEATURE=CHAT;
|
||||
LABEL=Chat room:xmpp:chat-123@conference.example.com
|
||||
CONFERENCE;VALUE=URI;FEATURE=AUDIO,VIDEO;
|
||||
LABEL=Attendee dial-in:https://chat.example.com/audio?id=123456
|
||||
"""
|
||||
|
||||
# see https://stackoverflow.com/a/18348004/1320237
|
||||
uri: str
|
||||
feature: list[str] | str | None = None
|
||||
label: list[str] | str | None = None
|
||||
language: list[str] | str | None = None
|
||||
|
||||
@classmethod
|
||||
def from_uri(cls, uri: vUri):
|
||||
"""Create a Conference from a URI."""
|
||||
return cls(
|
||||
uri,
|
||||
feature=uri.params.get("feature"),
|
||||
label=uri.params.get("label"),
|
||||
language=uri.params.get("language"),
|
||||
)
|
||||
|
||||
def to_uri(self) -> vUri:
|
||||
"""Convert the Conference to a vUri."""
|
||||
params = {}
|
||||
if self.feature:
|
||||
params["FEATURE"] = self.feature
|
||||
if self.label:
|
||||
params["LABEL"] = self.label
|
||||
if self.language:
|
||||
params["LANGUAGE"] = self.language
|
||||
return vUri(self.uri, params=params)
|
||||
|
||||
|
||||
__all__ = ["Conference"]
|
|
@ -0,0 +1,14 @@
|
|||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE,MODERATOR;
|
||||
LABEL=Moderator dial-in:tel:+1-412-555-0123,,,654321
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE;
|
||||
LABEL=Attendee dial-in:tel:+1-412-555-0123,,,555123
|
||||
CONFERENCE;VALUE=URI;FEATURE=PHONE;
|
||||
LABEL=Attendee dial-in:tel:+1-888-555-0456,,,555123
|
||||
CONFERENCE;VALUE=URI;FEATURE=CHAT;
|
||||
LABEL=Chat room:xmpp:chat-123@conference.example.com
|
||||
CONFERENCE;VALUE=URI;FEATURE=AUDIO,VIDEO;
|
||||
LABEL=Attendee dial-in:https://chat.example.com/audio?id=123456
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
|
@ -0,0 +1,144 @@
|
|||
"""Test conference properties."""
|
||||
|
||||
import pytest
|
||||
|
||||
from icalendar import Calendar, Event, Todo, vUri
|
||||
from icalendar.prop.conference import Conference
|
||||
|
||||
|
||||
def test_from_empty_uri():
|
||||
"""Test creation from a URI."""
|
||||
conference = Conference.from_uri(vUri("https://chat.example.com/audio?id=123456"))
|
||||
assert conference.uri == "https://chat.example.com/audio?id=123456"
|
||||
assert conference.feature is None
|
||||
assert conference.label is None
|
||||
assert conference.language is None
|
||||
|
||||
|
||||
def test_from_example_uri():
|
||||
"""Create a conference with lots of values."""
|
||||
conference = Conference.from_uri(
|
||||
vUri(
|
||||
"https://chat.example.com/audio?id=123456",
|
||||
params={
|
||||
"FEATURE": "PHONE,MODERATOR",
|
||||
"LABEL": "Moderator dial-in",
|
||||
"LANGUAGE": "EN",
|
||||
},
|
||||
)
|
||||
)
|
||||
assert conference.uri == "https://chat.example.com/audio?id=123456"
|
||||
assert conference.feature == "PHONE,MODERATOR"
|
||||
assert conference.label == "Moderator dial-in"
|
||||
assert conference.language == "EN"
|
||||
|
||||
|
||||
def test_to_uri():
|
||||
"""Test creating a vURI."""
|
||||
uri = vUri(
|
||||
"https://chat.example.com/audio?id=123456",
|
||||
params={"FEATURE": "PHONE", "LABEL": "Moderator", "LANGUAGE": "DE"},
|
||||
)
|
||||
conference = Conference.from_uri(uri)
|
||||
new_uri = conference.to_uri()
|
||||
assert new_uri == uri
|
||||
assert new_uri.params == uri.params
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def conference_1():
|
||||
"""Fixture for a conference with a URI."""
|
||||
return Conference.from_uri(vUri("https://chat.example.com/audio?id=123456"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def conference_2():
|
||||
"""Fixture for a conference with a URI."""
|
||||
return Conference(
|
||||
vUri("https://chat.example.com/audio?id=123456"),
|
||||
feature="PHONE",
|
||||
label="Moderator dial-in",
|
||||
language="EN",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(params=[Event, Todo])
|
||||
def component_class(request):
|
||||
"""Fixture to create a Conference component."""
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def component(component_class):
|
||||
"""Create a component."""
|
||||
return component_class()
|
||||
|
||||
|
||||
def test_no_conferenes(component):
|
||||
"""No conferences by default."""
|
||||
assert component.conferences == []
|
||||
assert "CONFERENCE" not in component
|
||||
|
||||
|
||||
def test_add_conference(component, conference_1):
|
||||
"""Add a new conference."""
|
||||
component.conferences = [conference_1]
|
||||
assert component["CONFERENCE"] == conference_1.to_vUri()
|
||||
|
||||
|
||||
def test_add_multiple_conferences(component, conference_1, conference_2):
|
||||
"""Add a new conference."""
|
||||
component.conferences = [conference_1, conference_2]
|
||||
assert component["CONFERENCE"] == [conference_1.to_vUri(), conference_2.to_vUri()]
|
||||
|
||||
|
||||
def test_new_component_with_conferences(component_class, conference_1, conference_2):
|
||||
"""Create a new component with conferences."""
|
||||
component = component_class.new(conferences=[conference_1, conference_2])
|
||||
assert component.conferences == [conference_1, conference_2]
|
||||
|
||||
|
||||
def test_uri_in_ical_(conference_2, component):
|
||||
"""The URI start be in the ical string."""
|
||||
component.conferences = [conference_2]
|
||||
ical_str = component.to_ical().decode("utf-8")
|
||||
assert "CONFERENCE;" in ical_str
|
||||
assert "/audio?id=123456" in ical_str
|
||||
assert "PHONE" in ical_str
|
||||
|
||||
|
||||
def get_event(calendar: Calendar) -> Event:
|
||||
"""Get the event directly"""
|
||||
return calendar.events[0]
|
||||
|
||||
|
||||
def get_serialized_event(calendar: Calendar) -> Event:
|
||||
"""Get the event directly"""
|
||||
cal = Calendar.from_ical(calendar.to_ical())
|
||||
return cal.events[0]
|
||||
|
||||
|
||||
@pytest.fixture(params=[get_event, get_serialized_event])
|
||||
def event_with_conferences(request, calendars):
|
||||
"""Return the event from the file."""
|
||||
calendar = calendars.rfc_7986_conferences
|
||||
return request.param(calendar)
|
||||
|
||||
|
||||
def test_conferences_from_file(event_with_conferences):
|
||||
"""The conferences should be in the calendar."""
|
||||
assert len(event_with_conferences.conferences) == 5
|
||||
assert event_with_conferences.conferences[0].uri == "tel:+1-412-555-0123,,,654321"
|
||||
assert event_with_conferences.conferences[1].uri == "tel:+1-412-555-0123,,,555123"
|
||||
assert event_with_conferences.conferences[2].uri == "tel:+1-888-555-0456,,,555123"
|
||||
assert (
|
||||
event_with_conferences.conferences[3].uri
|
||||
== "xmpp:chat-123@conference.example.com"
|
||||
)
|
||||
assert (
|
||||
event_with_conferences.conferences[4].uri
|
||||
== "https://chat.example.com/audio?id=123456"
|
||||
)
|
||||
assert event_with_conferences.conferences[4].feature == ["AUDIO", "VIDEO"]
|
||||
assert event_with_conferences.conferences[4].label == "Attendee dial-in"
|
||||
assert event_with_conferences.conferences[4].language is None
|
Ładowanie…
Reference in New Issue