"""Unit tests for the Wekan metric source."""

from datetime import datetime
from typing import Dict

from tests.source_collectors.source_collector_test_case import SourceCollectorTestCase


class WekanTestCase(SourceCollectorTestCase):
    """Base class for testing Wekan collectors."""

    def setUp(self):
        super().setUp()
        self.sources = dict(
            source_id=dict(
                type="wekan",
                parameters=dict(
                    url="https://wekan", board="board1", username="user", password="<PASSWORD>",
                    inactive_days="90", lists_to_ignore=[])))
        self.json = [
            dict(_id="user_id"),
            [dict(_id="board1", title="Board 1", slug="board-slug")],
            [self.list(1), self.list(2), self.list(3, archived=True)],
            [self.card(1), self.card(2)],
            self.full_card(1),
            self.full_card(2),
            [self.card(3)],
            self.full_card(3)]
        self.entities = [self.entity(1, 1), self.entity(3, 2)]

    @staticmethod
    def card(index: int) -> Dict:
        """Create a card."""
        return dict(_id=f"card{index}", title=f"Card {index}")

    @classmethod
    def full_card(cls, index: int) -> Dict:
        """Create a full card."""
        return dict(archived=False, boardId="board1", dateLastActivity="2019-01-01", **cls.card(index))

    @staticmethod
    def list(index: int, archived: bool = False) -> Dict:
        """Create a list."""
        return dict(_id=f"list{index}", title=f"List {index}", archived=archived)

    @staticmethod
    def entity(card_index: int, list_index: int) -> Dict:
        """Return an entity"""
        return dict(
            key=f"card{card_index}", url=f"https://wekan/b/board1/board-slug/card{card_index}",
            title=f"Card {card_index}", list=f"List {list_index}", due_date="", date_last_activity="2019-01-01")


class WekanIssuesTest(WekanTestCase):
    """Unit tests for the Wekan issues collector."""

    def setUp(self):
        super().setUp()
        self.metric = dict(type="issues", addition="sum", sources=self.sources)

    async def test_issues(self):
        """Test that the number of issues and the individual issues are returned and that archived cards are ignored."""
        self.json[5]["archived"] = True
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="2", entities=self.entities)

    async def test_issues_with_ignored_list(self):
        """Test that lists can be ignored when counting issues."""
        self.sources["source_id"]["parameters"]["lists_to_ignore"] = ["list2"]
        self.json[5]["archived"] = True
        del self.entities[1]
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="1", entities=self.entities)

    async def test_overdue_issues(self):
        """Test overdue issues."""
        self.sources["source_id"]["parameters"]["cards_to_count"] = ["overdue"]
        self.entities[0]["due_date"] = self.json[4]["dueAt"] = "2019-01-01"
        self.entities[1]["due_date"] = self.json[7]["dueAt"] = "2019-02-02"
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="2", entities=self.entities)

    async def test_inactive_issues(self):
        """Test inactive issues."""
        self.sources["source_id"]["parameters"]["cards_to_count"] = ["inactive"]
        self.json[5]["dateLastActivity"] = datetime.now().isoformat()
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="2", entities=self.entities)


class WekanSourceUpToDatenessTest(WekanTestCase):
    """Unit tests for the Wekan source up-to-dateness collector."""

    async def test_age_with_ignored_lists(self):
        """Test that lists can be ignored when measuring the number of days since the last activity."""
        self.sources["source_id"]["parameters"]["lists_to_ignore"] = ["list1"]
        metric = dict(type="source_up_to_dateness", addition="max", sources=self.sources)
        response = await self.collect(
            metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value=str((datetime.now() - datetime(2019, 1, 1)).days))

"""Unit tests for the Wekan metric source."""

from datetime import datetime
from typing import Dict

from tests.source_collectors.source_collector_test_case import SourceCollectorTestCase


class WekanTestCase(SourceCollectorTestCase):
    """Base class for testing Wekan collectors."""

    def setUp(self):
        super().setUp()
        self.sources = dict(
            source_id=dict(
                type="wekan",
                parameters=dict(
                    url="https://wekan", board="board1", username="user", password="<PASSWORD>",
                    inactive_days="90", lists_to_ignore=[])))
        self.json = [
            dict(_id="user_id"),
            [dict(_id="board1", title="Board 1", slug="board-slug")],
            [self.list(1), self.list(2), self.list(3, archived=True)],
            [self.card(1), self.card(2)],
            self.full_card(1),
            self.full_card(2),
            [self.card(3)],
            self.full_card(3)]
        self.entities = [self.entity(1, 1), self.entity(3, 2)]

    @staticmethod
    def card(index: int) -> Dict:
        """Create a card."""
        return dict(_id=f"card{index}", title=f"Card {index}")

    @classmethod
    def full_card(cls, index: int) -> Dict:
        """Create a full card."""
        return dict(archived=False, boardId="board1", dateLastActivity="2019-01-01", **cls.card(index))

    @staticmethod
    def list(index: int, archived: bool = False) -> Dict:
        """Create a list."""
        return dict(_id=f"list{index}", title=f"List {index}", archived=archived)

    @staticmethod
    def entity(card_index: int, list_index: int) -> Dict:
        """Return an entity"""
        return dict(
            key=f"card{card_index}", url=f"https://wekan/b/board1/board-slug/card{card_index}",
            title=f"Card {card_index}", list=f"List {list_index}", due_date="", date_last_activity="2019-01-01")


class WekanIssuesTest(WekanTestCase):
    """Unit tests for the Wekan issues collector."""

    def setUp(self):
        super().setUp()
        self.metric = dict(type="issues", addition="sum", sources=self.sources)

    async def test_issues(self):
        """Test that the number of issues and the individual issues are returned and that archived cards are ignored."""
        self.json[5]["archived"] = True
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="2", entities=self.entities)

    async def test_issues_with_ignored_list(self):
        """Test that lists can be ignored when counting issues."""
        self.sources["source_id"]["parameters"]["lists_to_ignore"] = ["list2"]
        self.json[5]["archived"] = True
        del self.entities[1]
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="1", entities=self.entities)

    async def test_overdue_issues(self):
        """Test overdue issues."""
        self.sources["source_id"]["parameters"]["cards_to_count"] = ["overdue"]
        self.entities[0]["due_date"] = self.json[4]["dueAt"] = "2019-01-01"
        self.entities[1]["due_date"] = self.json[7]["dueAt"] = "2019-02-02"
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="2", entities=self.entities)

    async def test_inactive_issues(self):
        """Test inactive issues."""
        self.sources["source_id"]["parameters"]["cards_to_count"] = ["inactive"]
        self.json[5]["dateLastActivity"] = datetime.now().isoformat()
        response = await self.collect(
            self.metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value="2", entities=self.entities)


class WekanSourceUpToDatenessTest(WekanTestCase):
    """Unit tests for the Wekan source up-to-dateness collector."""

    async def test_age_with_ignored_lists(self):
        """Test that lists can be ignored when measuring the number of days since the last activity."""
        self.sources["source_id"]["parameters"]["lists_to_ignore"] = ["list1"]
        metric = dict(type="source_up_to_dateness", addition="max", sources=self.sources)
        response = await self.collect(
            metric, get_request_json_side_effect=self.json, post_request_json_return_value=dict(token="token"))
        self.assert_measurement(response, value=str((datetime.now() - datetime(2019, 1, 1)).days))

Unit tests for the Wekan metric source. Base class for testing Wekan collectors. Create a card. Create a full card. Create a list. Return an entity Unit tests for the Wekan issues collector. Test that the number of issues and the individual issues are returned and that archived cards are ignored. Test that lists can be ignored when counting issues. Test overdue issues. Test inactive issues. Unit tests for the Wekan source up-to-dateness collector. Test that lists can be ignored when measuring the number of days since the last activity.