def test_groupTogglByIssueId(self):
        entries = [
            TogglEntry(None, 3600, None, 1, "#15", self.redmine_config),
            TogglEntry(None, 3600, None, 2, "#16", self.redmine_config),
            TogglEntry(None, 3600, None, 3, "#16", self.redmine_config),
            TogglEntry(None, 3600, None, 4, "#16", self.redmine_config),
            TogglEntry(None, 3600, None, 5, "#17", self.redmine_config),
        ]

        groups = Synchronizer.groupTogglByIssueId(entries)

        self.assertIsNotNone(groups)

        self.assertEqual(3, len(groups))

        self.assertTrue("15" in groups)
        self.assertTrue("16" in groups)
        self.assertTrue("17" in groups)

        self.assertEquals(1, len(groups["15"]))
        self.assertEquals(3, len(groups["16"]))
        self.assertEquals(1, len(groups["17"]))

        self.assertEquals(1, groups["15"][0].id)
        self.assertEquals(2, groups["16"][0].id)
        self.assertEquals(3, groups["16"][1].id)
        self.assertEquals(4, groups["16"][2].id)
        self.assertEquals(5, groups["17"][0].id)
Exemplo n.º 2
0
    def test_filterToday(self):
        actual = MattermostNotifier.filterToday([
            TogglEntry(None, 4 * 3600, self.today, 777, "#666 Hardwork",
                       self.redmine_config),
            TogglEntry(None, 4 * 3600, None, 778, "#666 Hardwork",
                       self.redmine_config),
        ])

        self.assertEquals(1, len(actual))
        self.assertEquals(actual[0].id, 777)
Exemplo n.º 3
0
    def test_filterWithRedmineId(self):
        entries = [
            TogglEntry(None, 1, self.today, 1, "#666 Hardwork",
                       self.redmine_config),
            TogglEntry(None, 1, self.today, 2, "Hardwork",
                       self.redmine_config),
            TogglEntry(None, 1, self.today, 3, "#666 Hardwork",
                       self.redmine_config),
        ]

        filtered = MattermostNotifier.filterWithRedmineId(entries)

        self.assertEquals(2, len(filtered))
        self.assertEquals(1, filtered[0].id)
        self.assertEquals(3, filtered[1].id)
    def test_sync_single_toggl_no_redmine(self):
        config = MagicMock()
        redmine = RedmineHelper("url", None, False)
        redmine.get = Mock()
        redmine.put = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                3600,
                "2016-01-01T01:01:01",
                17,
                "#987 hard work",
                self.redmine_config,
            )
        ]

        redmine.get.return_value = []

        s = Synchronizer(config, redmine, toggl, None, raise_errors=True)
        s.start(1)

        toggl.get.assert_called_once_with(1)

        redmine.put.assert_called_once_with(
            issueId="987",
            spentOn="2016-01-01",
            hours=1.0,
            comment="#987 hard work [toggl#17]",
        )
Exemplo n.º 5
0
    def __append_redmine_summary(self, allEntries):
        redmineEntries = TogglHelper.filter_valid_entries(allEntries)

        if len(redmineEntries) > 0:
            self.append("---")
            self.append("**Redmine summary**")

            redmineIssuesSums = {}

            for e in redmineEntries:
                if e.taskId not in redmineIssuesSums:
                    redmineIssuesSums[e.taskId] = 0

                redmineIssuesSums[e.taskId] += e.duration

            longestTasks = sorted(redmineIssuesSums,
                                  key=lambda id: -redmineIssuesSums[id])[:3]

            self.append("You spent most time on:")

            for id in longestTasks:
                self.append("- #{}: {} h".format(
                    id, TogglEntry.secondsToHours(redmineIssuesSums[id])))

            self.append("")
    def test_sync_single_toggl_already_inserted_in_redmine(self):
        redmine = RedmineHelper("url", None, False)
        redmine.get = Mock()
        redmine.put = Mock()
        redmine.update = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                3600,
                "2016-01-01T01:01:01",
                17,
                "#987 hard work",
                self.redmine_config,
            )
        ]

        redmine.get.return_value = [
            RedmineTimeEntry(
                222,
                "2016-05-01T04:02:22",
                "john doe",
                1,
                "2016-01-01",
                "987",
                "#987 hard work [toggl#17]",
            )
        ]

        s = Synchronizer(MagicMock(), redmine, toggl, None, raise_errors=True)
        s.start(1)
        redmine.update.assert_not_called()
        redmine.put.assert_not_called()
    def test_sync_skipping_entries_under_1min(self):
        config = MagicMock()
        jira = JiraHelper(None, None, None, False)
        jira.get = Mock()
        jira.jira_api = Mock()
        # jira.put = Mock()
        jira.jira_api.add_worklog = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                29,  # time rounds to under 60 sec
                "2016-01-01T01:01:01",
                17,
                "SLUG-987 hard work",
                self.jira_config,
            )
        ]

        jira.get.return_value = []

        s = Synchronizer(config, jira, toggl, None, raise_errors=True)
        s.start(1)

        toggl.get.assert_called_once_with(1)
        jira.jira_api.add_worklog.assert_not_called()
    def test_start_one_day_single(self):
        jira = JiraHelper(None, None, None, False)
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(None, 3600, "2016-03-02T01:01:01", 777, "test SLUG-333",
                       self.jira_config)
        ]

        jira.get = Mock()
        jira.get.return_value = [
            JiraTimeEntry(
                777,
                "2016-01-01T01:02:03",
                "john doe",
                3600,
                "2016-03-02T01:01:01",
                "SLUG-333",
                "test SLUG-333 [toggl#777]",
            )
        ]
        jira.update = MagicMock()

        s = Synchronizer(Mock(), jira, toggl, None, raise_errors=True)
        s.start(1)

        toggl.get.assert_called_once_with(1)
        jira.get.assert_called_once_with('SLUG-333')
        jira.update.assert_not_called()
    def test_sync_single_toggl_update_to_under_1min_clears_worklog(self):
        jira = JiraHelper(None, None, None, False)
        jira.get = Mock()
        jira.delete = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                29,  # time rounds to under 60 sec
                "2016-01-01T01:01:01",
                17,
                "SLUG-987 hard work",
                self.jira_config,
            )
        ]

        jira.get.return_value = [
            JiraTimeEntry(
                222,
                "2016-05-01T04:02:22",
                "john doe",
                1000,
                "2016-01-01T01:01:01",
                "SLUG-987",
                "SLUG-987 hard work [toggl#17]",
            )
        ]

        s = Synchronizer(MagicMock(), jira, toggl, None, raise_errors=True)
        s.start(1)

        jira.delete.assert_called_once_with(222, "SLUG-987")
    def test_start_one_day_single(self):
        redmine = RedmineHelper("url", None, False)
        toggl = TogglHelper("url", None)

        toggl.get = MagicMock()
        toggl.get.return_value = [
            TogglEntry(None, 3600, "2016-03-02T01:01:01", 777, "test #333",
                       self.redmine_config)
        ]

        redmine.get = MagicMock()
        redmine.get.return_value = [
            RedmineTimeEntry(
                777,
                "2016-01-01T01:02:03",
                "john doe",
                1.0,
                "2016-03-02",
                333,
                "test #333 [toggl#777]",
            )
        ]
        redmine.update = MagicMock()

        s = Synchronizer(Mock(), redmine, toggl, None, raise_errors=True)
        s.start(1)

        toggl.get.assert_called_once_with(1)
        redmine.get.assert_called_once_with('333')
        redmine.update.assert_not_called()
    def test_sync_single_toggl_already_inserted_in_jira(self):
        jira = JiraHelper(None, None, None, False)
        jira.get = Mock()
        jira.put = Mock()
        jira.update = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                3600,
                "2016-01-01T01:01:01",
                17,
                "SLUG-987 hard work",
                self.jira_config,
            )
        ]

        jira.get.return_value = [
            JiraTimeEntry(
                222,
                "2016-05-01T04:02:22",
                "john doe",
                3600,
                "2016-01-01T01:01:01",
                "SLUG-987",
                "SLUG-987 hard work [toggl#17]",
            )
        ]

        s = Synchronizer(MagicMock(), jira, toggl, None, raise_errors=True)
        s.start(1)
        jira.update.assert_not_called()
        jira.put.assert_not_called()
    def test_sync_single_toggl_no_jira(self):
        config = MagicMock()
        jira = JiraHelper(None, None, None, False)
        jira.get = Mock()
        jira.put = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                3600,
                "2016-01-01T01:01:01",
                17,
                "SLUG-987 hard work",
                self.jira_config,
            )
        ]

        jira.get.return_value = []

        s = Synchronizer(config, jira, toggl, None, raise_errors=True)
        s.start(1)

        toggl.get.assert_called_once_with(1)

        jira.put.assert_called_once_with(
            issueId="SLUG-987",
            started="2016-01-01T01:01:01",
            seconds=3600,
            comment="SLUG-987 hard work [toggl#17]",
        )
Exemplo n.º 13
0
 def testDictFromTogglEntry(self):
     input = TogglEntry(None, 120, "2016-03-02T01:01:01", 777,
                        "test SLUG-333", self.jira_config)
     result = JiraHelper.dictFromTogglEntry(input)
     self.assertEquals("SLUG-333", result["issueId"])
     self.assertEquals("2016-03-02T01:01:01", result["started"])
     self.assertEquals(120, result["seconds"])
     self.assertEquals("test SLUG-333 [toggl#777]", result["comment"])
Exemplo n.º 14
0
    def test_append_redmine_summary_only_first_3(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)

        l = [
            TogglEntry(None, 3600, self.today, 777, "test #333",
                       self.redmine_config),
            TogglEntry(None, 3600, self.today, 777, "test #333",
                       self.redmine_config),
            TogglEntry(None, 3600, self.today, 777, "test #333",
                       self.redmine_config),
            TogglEntry(None, 3600, self.today, 777, "test #333",
                       self.redmine_config),
            TogglEntry(None, 0.5 * 3600, self.today, 778, "test #334",
                       self.redmine_config),
            TogglEntry(None, 2 * 3600, self.today, 778, "test #335",
                       self.redmine_config),
            TogglEntry(None, 10 * 3600, self.today, 778, "test #400",
                       self.redmine_config),
        ]

        mattermost._MattermostNotifier__append_redmine_summary(l)
        mattermost.send()

        text = """---
**Redmine summary**
You spent most time on:
- #400: 10.0 h
- #333: 4.0 h
- #335: 2.0 h
"""

        runner.send.assert_called_with(text)
Exemplo n.º 15
0
 def test_parse(self):
     toggl_payload = {
         "id": 2121,
         "duration": 255,
         "start": "2016-01-01T09:09:09+02:00",
         "description": "entry description",
     }
     entry = TogglEntry.createFromEntry(toggl_payload, None)
     self.assertEquals(2121, entry.id)
     self.assertEquals("2016-01-01T07:09:09+00:00", entry.start)
    def test_ignore_negative_duration(self):
        """
        Synchronizer should ignore entries with negative durations (pending entries).

		From toggl docs:
           duration: time entry duration in seconds. If the time entry is currently running, the duration attribute contains a negative value, denoting the start
           of the time entry in seconds since epoch (Jan 1 1970). The correct duration can be calculated as current_time + duration, where current_time is the current
           time in seconds since epoch. (integer, required)
        """

        redmine = RedmineHelper("url", None, False)
        redmine.get = Mock()
        redmine.put = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(None, 3600, "2016-01-01T01:01:01", 777, "test #333",
                       self.redmine_config),
            TogglEntry(
                None,
                -3600,
                "2016-01-01T01:01:01",
                778,
                "test #334",
                self.redmine_config,
            ),
        ]

        redmine.get.return_value = []

        s = Synchronizer(Mock(), redmine, toggl, None, raise_errors=True)
        s.start(1)

        toggl.get.assert_called_once_with(1)
        redmine.get.assert_called_once_with("333")

        redmine.put.assert_called_once_with(
            issueId="333",
            spentOn="2016-01-01",
            hours=1.0,
            comment="test #333 [toggl#777]",
        )
Exemplo n.º 17
0
    def test_append_summary_3_entries_1_redmine(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)

        l = [
            TogglEntry(None, 60, self.today, 777, "#666 Hardwork",
                       self.redmine_config),
            TogglEntry(None, 60, self.today, 777, "Hardwork",
                       self.redmine_config),
            TogglEntry(None, 60, self.today, 777, "Hardwork",
                       self.redmine_config),
        ]

        mattermost._MattermostNotifier__append_summary(l)
        mattermost.send()

        text = """You worked almost less than 4 hours today (exactly 3 m), not every day is a perfect day, right? :smirk:.
Huh, not many entries. It means, you did only a couple of tasks, but did it right .. right? :open_mouth:
Almost 50% of your today work had redmine id :blush:."""

        runner.send.assert_called_with(text)
Exemplo n.º 18
0
 def test_repr(self):
     entry = TogglEntry(
         None,
         8100,
         "2016-01-01T09:09:09+02:00",
         999,
         "comment SLUG-123",
         self.sample_config,
     )
     self.assertEquals(
         "toggl#999. 2016-01-01T09:09:09+02:00: comment SLUG-123 (time: 2.25 h, task id: SLUG-123)",
         repr(entry),
     )
 def create_test_entries_pair(self):
     toggl = TogglEntry(None, 3600, "2020-01-13T08:11:04+00:00", 777,
                        "test SLUG-333", self.jira_config)
     jira = JiraTimeEntry(
         "987654321",
         created_on="2020-01-13T08:11:04.000+00:00",
         user="******",
         seconds=3600,
         started="2020-01-13T08:11:04.000+00:00",
         issue="SLUG-333",
         comments="test SLUG-333 [toggl#777]",
         jira_issue_id="12345",
     )
     return toggl, jira
Exemplo n.º 20
0
    def test_append_entries_two_one_with_redmine(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)
        mattermost.appendEntries([
            TogglEntry(None, 60, self.today, 776, "", self.redmine_config),
            TogglEntry(None, 60, self.today, 777, "#666 Hardwork",
                       self.redmine_config),
        ])
        mattermost.send()

        text = """Found entries in toggl: **2** (filtered: **1**)
You worked almost less than 4 hours today (exactly 2 m), not every day is a perfect day, right? :smirk:.
Huh, not many entries. It means, you did only a couple of tasks, but did it right .. right? :open_mouth:
It's gooood. A lot of today work had redmine id! Congrats :sunglasses:.

---
**Redmine summary**
You spent most time on:
- #666: 0.02 h
"""

        runner.send.assert_called_with(text)
Exemplo n.º 21
0
 def test_str(self):
     entry = TogglEntry(
         None,
         8145,
         "2016-01-01T10:09:09-00:00",
         999,
         "comment SLUG-123",
         self.sample_config,
     )
     with mock.patch("dateutil.tz.tzlocal",
                     return_value=dateutil.tz.gettz("EST")):
         self.assertEquals(
             "2016-01-01 05:09: comment SLUG-123, spent: 2:15:45, issue: SLUG-123 [toggl#999]",
             str(entry),
         )
Exemplo n.º 22
0
    def test_append_summary_two_one_with_redmine_4_hours(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)
        mattermost._MattermostNotifier__append_summary([
            TogglEntry(None, 4 * 3123, self.today, 777, "#666 Hardwork",
                       self.redmine_config)
        ])
        mattermost.send()

        text = """You worked almost less than 4 hours today (exactly 3.47 h), not every day is a perfect day, right? :smirk:.
Huh, not many entries. It means, you did only a couple of tasks, but did it right .. right? :open_mouth:
It seems that more than 75% of your today work had redmine id! So .. you rock :rocket:!"""

        runner.send.assert_called_with(text)
Exemplo n.º 23
0
    def test_append_entries_one(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)
        mattermost.appendEntries(
            [TogglEntry(None, 60, self.today, 777, "", self.redmine_config)])
        mattermost.send()

        text = """Found entries in toggl: **1** (filtered: **0**)
You worked almost less than 4 hours today (exactly 1 m), not every day is a perfect day, right? :smirk:.
Huh, not many entries. It means, you did only a couple of tasks, but did it right .. right? :open_mouth:
Ugh. Less than 25% of your work had redmine id. Not so good :cry:.
"""

        runner.send.assert_called_with(text)
Exemplo n.º 24
0
    def test_ignore_negative_duration(self):
        """
        Mattermost should ignore entries with negative durations (pending entries).

		From toggl docs:
           duration: time entry duration in seconds. If the time entry is currently running, the duration attribute contains a negative value, denoting the start
           of the time entry in seconds since epoch (Jan 1 1970). The correct duration can be calculated as current_time + duration, where current_time is the current
           time in seconds since epoch. (integer, required)
        """

        runner = MagicMock()

        mattermost = MattermostNotifier(runner)

        l = [
            TogglEntry(None, 3600, self.today, 777, "test #333",
                       self.redmine_config),
            TogglEntry(None, -300, self.today, 778, "test #334",
                       self.redmine_config),
        ]

        mattermost.appendEntries(l)
        mattermost.send()

        text = """Found entries in toggl: **2** (filtered: **1**)
You worked almost less than 4 hours today (exactly 1.00 h), not every day is a perfect day, right? :smirk:.
Huh, not many entries. It means, you did only a couple of tasks, but did it right .. right? :open_mouth:
It seems that more than 75% of your today work had redmine id! So .. you rock :rocket:!

---
**Redmine summary**
You spent most time on:
- #333: 1.0 h
"""

        runner.send.assert_called_with(text)
Exemplo n.º 25
0
    def test_append_redmine_summary_no_entries_no_summary(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)

        l = [
            TogglEntry(None, 3600, self.today, 777, "test 333",
                       self.redmine_config)
        ]

        mattermost._MattermostNotifier__append_redmine_summary(l)
        mattermost.send()

        text = ""

        runner.send.assert_called_with(text)
Exemplo n.º 26
0
    def test_append_summary_50_entries(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)

        e = TogglEntry(None, 60, self.today, 777, "#666 Hardwork",
                       self.redmine_config)
        l = []

        for i in range(50):
            l.append(e)

        mattermost._MattermostNotifier__append_summary(l)
        mattermost.send()

        text = """You worked almost less than 4 hours today (exactly 50 m), not every day is a perfect day, right? :smirk:.
You did 50 entries like a boss :smirk: :boom:!
It seems that more than 75% of your today work had redmine id! So .. you rock :rocket:!"""

        runner.send.assert_called_with(text)
Exemplo n.º 27
0
    def test_append_summary_10_entries(self):
        runner = MagicMock()

        mattermost = MattermostNotifier(runner)

        e = TogglEntry(None, 4 * 3600, self.today, 777, "#666 Hardwork",
                       self.redmine_config)
        l = []

        for i in range(1, 10):
            l.append(e)

        mattermost._MattermostNotifier__append_summary(l)
        mattermost.send()

        text = """Wow you did overtime today :rocket:! Doing overtime from time to time can be good, but life after work is also important. Remember this next time taking 36.00 h in work :sunglasses:!
Average day. Not too few, not too many entries :sunglasses:.
It seems that more than 75% of your today work had redmine id! So .. you rock :rocket:!"""

        runner.send.assert_called_with(text)
    def test_sync_single_toggl_modified_entry(self):
        jira = JiraHelper(None, None, None, False)
        jira.get = Mock()
        jira.update = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                2 * 3600,
                "2016-01-01T01:01:01",
                17,
                "SLUG-987 hard work",
                self.jira_config,
            )
        ]

        jira.get.return_value = [
            JiraTimeEntry(
                222,
                "2016-05-01T04:02:22",
                "john doe",
                1,
                "2016-01-01T01:01:01",
                "SLUG-987",
                "SLUG-987 hard work [toggl#17]",
            )
        ]

        s = Synchronizer(MagicMock(), jira, toggl, None, raise_errors=True)
        s.start(1)

        jira.update.assert_called_once_with(
            id=222,
            issueId="SLUG-987",
            started="2016-01-01T01:01:01",
            seconds=2 * 3600,
            comment="SLUG-987 hard work [toggl#17]",
        )
    def test_sync_single_toggl_modified_entry(self):
        redmine = RedmineHelper("url", None, False)
        redmine.get = Mock()
        redmine.update = Mock()
        toggl = TogglHelper("url", None)
        toggl.get = Mock()

        toggl.get.return_value = [
            TogglEntry(
                None,
                2 * 3600,
                "2016-01-01T01:01:01",
                17,
                "#987 hard work",
                self.redmine_config,
            )
        ]

        redmine.get.return_value = [
            RedmineTimeEntry(
                222,
                "2016-05-01T04:02:22",
                "john doe",
                1,
                "2016-01-01",
                "987",
                "#987 hard work [toggl#17]",
            )
        ]

        s = Synchronizer(MagicMock(), redmine, toggl, None, raise_errors=True)
        s.start(1)

        redmine.update.assert_called_once_with(
            id=222,
            issueId="987",
            spentOn="2016-01-01",
            hours=2.0,
            comment="#987 hard work [toggl#17]",
        )
Exemplo n.º 30
0
 def testDictFromTogglEntry_time_is_rounded(self):
     input = TogglEntry(None, 151, "2016-03-02T01:01:01", 777,
                        "test SLUG-333", self.jira_config)
     result = JiraHelper.dictFromTogglEntry(input)
     self.assertEquals(180, result["seconds"])