Skip to content

rss.testing

rss.testing

RssTestApp dataclass

Helper class to provide a server that serves an RSS feed

Automatically starts a server on creation.

Source code in rss/testing/__init__.py
@dataclass
class RssTestApp:
    """Helper class to provide a server that serves an RSS feed

    Automatically starts a server on creation.
    """

    port: int = 80
    """The port the server will run on"""
    feed: FeedMock = field(default_factory=lambda: FeedMock())
    """The feed being server"""

    def __post_init__(self):
        self.app = Quart(__name__)

        @self.app.get("/")
        async def main():
            return self.feed.response()

        self.task = asyncio.create_task(
            self.app.run_task(port=self.port, host="0.0.0.0")
        )

    async def cancel(self):
        """Await this to ensure the server shuts down"""
        self.task.cancel()

        try:
            await self.task
        except asyncio.CancelledError:
            ...

feed: FeedMock = field(default_factory=(lambda: FeedMock())) class-attribute instance-attribute

The feed being server

port: int = 80 class-attribute instance-attribute

The port the server will run on

cancel() async

Await this to ensure the server shuts down

Source code in rss/testing/__init__.py
async def cancel(self):
    """Await this to ensure the server shuts down"""
    self.task.cancel()

    try:
        await self.task
    except asyncio.CancelledError:
        ...

database() async

Fixture that ensures the database exists

Source code in rss/testing/__init__.py
@pytest.fixture(autouse=True)
async def database():
    """Fixture that ensures the database exists"""
    async with with_database():
        yield "db"

rss.testing.feed

FeedMock dataclass

Creates a basic mocked feed

>>> feed = FeedMock()
>>> print(feed.build())
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">test rss</title>
  <id>1</id>
  <updated>...</updated>
  <author>
    <name>Unknown author</name>
  </author>
  <generator>Werkzeug</generator>
  <entry>
    <title type="text">test_title</title>
    <id>1</id>
    <updated>...</updated>
  </entry>
</feed>
<BLANKLINE>
Source code in rss/testing/feed.py
@dataclass
class FeedMock:
    """Creates a basic mocked feed

    ```pycon
    >>> feed = FeedMock()
    >>> print(feed.build())
    <?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
      <title type="text">test rss</title>
      <id>1</id>
      <updated>...</updated>
      <author>
        <name>Unknown author</name>
      </author>
      <generator>Werkzeug</generator>
      <entry>
        <title type="text">test_title</title>
        <id>1</id>
        <updated>...</updated>
      </entry>
    </feed>
    <BLANKLINE>

    ```
    """

    feed: AtomFeed = field(default_factory=lambda: AtomFeed("test rss", id=1))

    def __post_init__(self):
        self.feed.add(title="test_title", id=1, updated=datetime.datetime.now())

    def build(self):
        """Returns feed content as string"""
        return str(self.feed)

    def add_entry(self, title, subtitle):
        """Adds a new entry to the feed

        ```pycon
        >>> feed = FeedMock().add_entry("new", None)
        >>> print(feed.build())
        <?xml version="1.0" encoding="utf-8"?>
        <feed xmlns="http://www.w3.org/2005/Atom">
        <title type="text">test rss</title>
        <id>1</id>
        <updated>...</updated>
        <author>
            <name>Unknown author</name>
        </author>
        <generator>Werkzeug</generator>
        <entry>
            <title type="text">test_title</title>
            <id>1</id>
            <updated>...</updated>
        </entry>
        <entry>
            <title type="text">new</title>
            <id>2</id>
            <updated>...</updated>
        </entry>
        </feed>
        <BLANKLINE>

        ```
        """

        self.feed.add(
            title=title,
            summary=subtitle,
            id=len(self.feed.entries) + 1,
            updated=datetime.datetime.now(),
        )
        return self

    def response(self):
        """Response for feed content with correct content type"""
        return self.build(), 200, {"content-type": "application/rss+xml"}

add_entry(title, subtitle)

Adds a new entry to the feed

>>> feed = FeedMock().add_entry("new", None)
>>> print(feed.build())
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">test rss</title>
<id>1</id>
<updated>...</updated>
<author>
    <name>Unknown author</name>
</author>
<generator>Werkzeug</generator>
<entry>
    <title type="text">test_title</title>
    <id>1</id>
    <updated>...</updated>
</entry>
<entry>
    <title type="text">new</title>
    <id>2</id>
    <updated>...</updated>
</entry>
</feed>
<BLANKLINE>
Source code in rss/testing/feed.py
def add_entry(self, title, subtitle):
    """Adds a new entry to the feed

    ```pycon
    >>> feed = FeedMock().add_entry("new", None)
    >>> print(feed.build())
    <?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
    <title type="text">test rss</title>
    <id>1</id>
    <updated>...</updated>
    <author>
        <name>Unknown author</name>
    </author>
    <generator>Werkzeug</generator>
    <entry>
        <title type="text">test_title</title>
        <id>1</id>
        <updated>...</updated>
    </entry>
    <entry>
        <title type="text">new</title>
        <id>2</id>
        <updated>...</updated>
    </entry>
    </feed>
    <BLANKLINE>

    ```
    """

    self.feed.add(
        title=title,
        summary=subtitle,
        id=len(self.feed.entries) + 1,
        updated=datetime.datetime.now(),
    )
    return self

build()

Returns feed content as string

Source code in rss/testing/feed.py
def build(self):
    """Returns feed content as string"""
    return str(self.feed)

response()

Response for feed content with correct content type

Source code in rss/testing/feed.py
def response(self):
    """Response for feed content with correct content type"""
    return self.build(), 200, {"content-type": "application/rss+xml"}