class TestPublishingGithubReleaseNotesGenerator(unittest.TestCase,
                                                GithubApiTestMixin):
    def setUp(self):
        self.init_github()
        self.github_info = {
            "github_owner": "TestOwner",
            "github_repo": "TestRepo",
            "github_username": "******",
            "github_password": "******",
            "master_branch": "master",
        }
        self.gh = get_github_api("TestUser", "TestPass")
        self.mock_util = MockUtil("TestOwner", "TestRepo")

    @responses.activate
    def test_publish_update_unicode(self):
        tag = "prod/1.4"
        note = u"“Unicode quotes”"
        expected_release_body = u"# Changes\r\n\r\n{}".format(note)
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        # create generator instance
        generator = self._create_generator(tag)
        # inject content into Changes parser
        generator.parsers[1].content.append(note)
        # render content
        content = generator.render()
        # verify
        self.assertEqual(len(responses.calls._calls), 1)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_no_body(self):
        tag = "prod/1.4"
        expected_release_body = "# Changes\r\n\r\nfoo"
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        # create generator
        generator = self._create_generator(tag)
        # inject content into Changes parser
        generator.parsers[1].content.append("foo")
        # render content
        content = generator.render()
        # verify
        self.assertEqual(len(responses.calls._calls), 1)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_before(self):
        tag = "prod/1.4"
        expected_release_body = "foo\r\n# Changes\r\n\r\nbaz"
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(tag=tag, body="foo\n# Changes\nbar")
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append("baz")
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_after(self):
        tag = "prod/1.4"
        expected_release_body = "# Changes\r\n\r\nbaz\r\n\r\n# Foo\r\nfoo"
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(tag=tag,
                                          body="# Changes\nbar\n# Foo\nfoo")
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append("baz")
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_before_and_after(self):
        tag = "prod/1.4"
        expected_release_body = "foo\r\n# Changes\r\n\r\nbaz\r\n\r\n# Foo\r\nfoo"
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag, body="foo\n# Changes\nbar\n# Foo\nfoo")
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append("baz")
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_between(self):
        tag = "prod/1.4"
        expected_release_body = ("# Critical Changes\r\n\r\nfaz\r\n\r\n"
                                 "# Foo\r\nfoo\r\n# Changes\r\n\r\nfiz")
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag,
            body="# Critical Changes\nbar\n# Foo\nfoo\n# Changes\nbiz")
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[0].content.append("faz")
        generator.parsers[1].content.append("fiz")
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_before_after_and_between(self):
        tag = "prod/1.4"
        expected_release_body = (
            "goo\r\n# Critical Changes\r\n\r\nfaz\r\n\r\n"
            "# Foo\r\nfoo\r\n# Changes\r\n\r\nfiz\r\n\r\n# Zoo\r\nzoo")
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag,
            body=("goo\n# Critical Changes\nbar\n"
                  "# Foo\nfoo\n# Changes\nbiz\n# Zoo\nzoo"),
        )
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[0].content.append("faz")
        generator.parsers[1].content.append("fiz")
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_missing(self):
        tag = "prod/1.4"
        expected_release_body = "foo\r\n# Changes\r\n\r\nbaz\r\n"
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(tag=tag, body="foo")
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append("baz")
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    def _create_generator(self, current_tag, last_tag=None):
        generator = GithubReleaseNotesGenerator(self.gh,
                                                self.github_info.copy(),
                                                PARSER_CONFIG, current_tag,
                                                last_tag)
        return generator

    @mock.patch(
        "cumulusci.tasks.release_notes.generator.BaseReleaseNotesGenerator.__call__"
    )
    @responses.activate
    def test_call(self, base_generator):
        self.mock_util.mock_get_repo()
        generator = self._create_generator("prod/1.0")
        generator.do_publish = True
        release = mock.Mock()
        generator._get_release = mock.Mock(return_value=release)
        generator._update_release_content = mock.Mock(
            return_value=mock.sentinel.content)
        result = generator()
        self.assertIs(mock.sentinel.content, result)
        base_generator.assert_called_once()
        release.edit.assert_called_once()

    @responses.activate
    def test_call__no_release(self):
        self.mock_util.mock_get_repo()
        generator = self._create_generator("prod/1.0")
        generator._get_release = mock.Mock(return_value=None)
        with self.assertRaises(CumulusCIException):
            result = generator()
class TestPublishingGithubReleaseNotesGenerator(unittest.TestCase, GithubApiTestMixin):

    def setUp(self):
        self.init_github()
        self.github_info = {
            'github_owner': 'TestOwner',
            'github_repo': 'TestRepo',
            'github_username': '******',
            'github_password': '******',
            'master_branch': 'master',
        }
        self.gh = get_github_api('TestUser', 'TestPass')
        self.mock_util = MockUtil('TestOwner', 'TestRepo')

    @responses.activate
    def test_publish_update_unicode(self):
        tag = 'prod/1.4'
        note = u'“Unicode quotes”'
        expected_release_body = u'# Changes\r\n\r\n{}'.format(note)
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        # create generator instance
        generator = self._create_generator(tag)
        # inject content into Changes parser
        generator.parsers[1].content.append(note)
        # render content
        content = generator.render()
        # verify
        self.assertEqual(len(responses.calls._calls), 1)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_no_body(self):
        tag = 'prod/1.4'
        expected_release_body = '# Changes\r\n\r\nfoo'
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        # create generator
        generator = self._create_generator(tag)
        # inject content into Changes parser
        generator.parsers[1].content.append('foo')
        # render content
        content = generator.render()
        # verify
        self.assertEqual(len(responses.calls._calls), 1)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_before(self):
        tag = 'prod/1.4'
        expected_release_body = 'foo\r\n# Changes\r\n\r\nbaz'
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(tag=tag, body='foo\n# Changes\nbar')
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append('baz')
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_after(self):
        tag = 'prod/1.4'
        expected_release_body = '# Changes\r\n\r\nbaz\r\n\r\n# Foo\r\nfoo'
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag,
            body='# Changes\nbar\n# Foo\nfoo',
        )
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append('baz')
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_before_and_after(self):
        tag = 'prod/1.4'
        expected_release_body = (
            'foo\r\n# Changes\r\n\r\nbaz\r\n\r\n# Foo\r\nfoo'
        )
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag,
            body='foo\n# Changes\nbar\n# Foo\nfoo',
        )
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[1].content.append('baz')
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_between(self):
        tag = 'prod/1.4'
        expected_release_body = (
            '# Critical Changes\r\n\r\nfaz\r\n\r\n'
            '# Foo\r\nfoo\r\n# Changes\r\n\r\nfiz'
        )
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag,
            body='# Critical Changes\nbar\n# Foo\nfoo\n# Changes\nbiz',
        )
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[0].content.append('faz')
        generator.parsers[1].content.append('fiz')
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    @responses.activate
    def test_publish_update_content_before_after_and_between(self):
        tag = 'prod/1.4'
        expected_release_body = (
            'goo\r\n# Critical Changes\r\n\r\nfaz\r\n\r\n'
            '# Foo\r\nfoo\r\n# Changes\r\n\r\nfiz\r\n\r\n# Zoo\r\nzoo'
        )
        # mock GitHub API responses
        self.mock_util.mock_get_repo()
        self.mock_util.mock_list_releases(
            tag=tag,
            body=(
                'goo\n# Critical Changes\nbar\n'
                '# Foo\nfoo\n# Changes\nbiz\n# Zoo\nzoo'
            ),
        )
        # create generator
        generator = self._create_generator(tag)
        # inject content into parser
        generator.parsers[0].content.append('faz')
        generator.parsers[1].content.append('fiz')
        # render and update content
        content = generator.render()
        release = generator._get_release()
        content = generator._update_release_content(release, content)
        # verify
        self.assertEqual(len(responses.calls._calls), 3)
        self.assertEqual(content, expected_release_body)

    def _create_generator(self, current_tag, last_tag=None):
        generator = GithubReleaseNotesGenerator(
            self.gh,
            self.github_info.copy(),
            PARSER_CONFIG,
            current_tag,
            last_tag,
        )
        return generator