# Path: bugwarrior/services/gerrit.py
# class GerritService(IssueService, ServiceClient):
#     ISSUE_CLASS = GerritIssue
#     CONFIG_SCHEMA = GerritConfig
# 
#     def __init__(self, *args, **kw):
#         super().__init__(*args, **kw)
#         self.password = self.get_password('password', self.config.username)
#         self.session = requests.session()
#         self.session.headers.update({
#             'Accept': 'application/json',
#             'Accept-Encoding': 'gzip',
#         })
#         self.query_string = (
#             self.config.query + '&o=MESSAGES&o=DETAILED_ACCOUNTS')
# 
#         if self.config.ssl_ca_path:
#             self.session.verify = self.config.ssl_ca_path
# 
#         # uses digest authentication if supported by the server, fallback to basic
#         # gerrithub.io supports only basic
#         response = self.session.head(self.config.base_uri + '/a/')
#         if 'digest' in response.headers.get('www-authenticate', '').lower():
#             self.session.auth = requests.auth.HTTPDigestAuth(
#                 self.config.username, self.password)
#         else:
#             self.session.auth = requests.auth.HTTPBasicAuth(
#                 self.config.username, self.password)
# 
#     @staticmethod
#     def get_keyring_service(config):
#         return f"gerrit://{config.base_uri}"
# 
#     def get_service_metadata(self):
#         return {
#             'url': self.config.base_uri,
#         }
# 
#     def get_owner(self, issue):
#         # TODO
#         raise NotImplementedError(
#             "This service has not implemented support for 'only_if_assigned'.")
# 
#     def issues(self):
#         # Construct the whole url by hand here, because otherwise requests will
#         # percent-encode the ':' characters, which gerrit doesn't like.
#         url = self.config.base_uri + '/a/changes/?q=' + self.query_string
#         response = self.session.get(url)
#         response.raise_for_status()
#         # The response has some ")]}'" garbage prefixed.
#         body = response.text[4:]
#         changes = json.loads(body)
# 
#         for change in changes:
#             extra = {
#                 'url': self.build_url(change),
#                 'annotations': self.annotations(change),
#             }
#             yield self.get_issue_for_record(change, extra)
# 
#     def build_url(self, change):
#         return '%s/#/c/%i/' % (self.config.base_uri, change['_number'])
# 
#     def annotations(self, change):
#         entries = []
#         for item in change['messages']:
#             for key in ['name', 'username', 'email']:
#                 if key in item['author']:
#                     username = item['author'][key]
#                     break
#             else:
#                 username = item['author']['_account_id']
#             # Gerrit messages are really messy
#             message = item['message']\
#                 .lstrip('Patch Set ')\
#                 .lstrip("%s:" % item['_revision_number'])\
#                 .strip()\
#                 .replace('\n', ' ')
#             entries.append((username, message,))
# 
#         return self.build_annotations(entries, self.build_url(change))
# 
# Path: tests/base.py
# class ServiceTest(ConfigTest):
#     GENERAL_CONFIG = {
#         'interactive': False,
#         'annotation_length': 100,
#         'description_length': 100,
#     }
#     SERVICE_CONFIG = {
#     }
# 
#     @classmethod
#     def setUpClass(cls):
#         cls.maxDiff = None
# 
#     def get_mock_service(
#         self, service_class, section='unspecified',
#         config_overrides=None, general_overrides=None
#     ):
#         options = {
#             'general': {**self.GENERAL_CONFIG, 'targets': section},
#             section: self.SERVICE_CONFIG.copy(),
#         }
#         if config_overrides:
#             options[section].update(config_overrides)
#         if general_overrides:
#             options['general'].update(general_overrides)
# 
#         service_config = service_class.CONFIG_SCHEMA(**options[section])
#         main_config = schema.MainSectionConfig(**options['general'])
#         main_config.data = data.BugwarriorData(self.lists_path)
# 
#         return service_class(service_config, main_config, section)
# 
#     @staticmethod
#     def add_response(url, **kwargs):
#         responses.add(responses.GET, url, match_querystring=True, **kwargs)
# 
# class AbstractServiceTest(abc.ABC):
#     """ Ensures that certain test methods are implemented for each service. """
#     @abc.abstractmethod
#     def test_to_taskwarrior(self):
#         """ Test Service.to_taskwarrior(). """
#         raise NotImplementedError
# 
#     @abc.abstractmethod
#     def test_issues(self):
#         """
#         Test Service.issues().
# 
#         - When the API is accessed via requests, use the responses library to
#         mock requests.
#         - When the API is accessed via a third party library, substitute a fake
#         implementation class for it.
#         """
#         raise NotImplementedError


import json
import responses
from bugwarrior.services.gerrit import GerritService
from .base import ServiceTest, AbstractServiceTest



class TestGerritIssue(AbstractServiceTest, ServiceTest):
    SERVICE_CONFIG = {
        'service': 'gerrit',
        'gerrit.base_uri': 'https://one.com',
        'gerrit.username': 'two',
        'gerrit.password': 'three',
    }

    record = {
        'project': 'nova',
        '_number': 1,
        'branch': 'master',
        'topic': 'test-topic',
        'subject': 'this is a title',
        'messages': [{'author': {'username': 'Iam Author'},
                      'message': 'this is a message',
                      '_revision_number': 1}],
    }

    def setUp(self):
        super().setUp()

        responses.add(
            responses.HEAD,
            self.SERVICE_CONFIG['gerrit.base_uri'] + '/a/',
            headers={'www-authenticate': 'digest'})
        with responses.mock:

# Path: bugwarrior/services/gerrit.py
# class GerritService(IssueService, ServiceClient):
#     ISSUE_CLASS = GerritIssue
#     CONFIG_SCHEMA = GerritConfig
# 
#     def __init__(self, *args, **kw):
#         super().__init__(*args, **kw)
#         self.password = self.get_password('password', self.config.username)
#         self.session = requests.session()
#         self.session.headers.update({
#             'Accept': 'application/json',
#             'Accept-Encoding': 'gzip',
#         })
#         self.query_string = (
#             self.config.query + '&o=MESSAGES&o=DETAILED_ACCOUNTS')
# 
#         if self.config.ssl_ca_path:
#             self.session.verify = self.config.ssl_ca_path
# 
#         # uses digest authentication if supported by the server, fallback to basic
#         # gerrithub.io supports only basic
#         response = self.session.head(self.config.base_uri + '/a/')
#         if 'digest' in response.headers.get('www-authenticate', '').lower():
#             self.session.auth = requests.auth.HTTPDigestAuth(
#                 self.config.username, self.password)
#         else:
#             self.session.auth = requests.auth.HTTPBasicAuth(
#                 self.config.username, self.password)
# 
#     @staticmethod
#     def get_keyring_service(config):
#         return f"gerrit://{config.base_uri}"
# 
#     def get_service_metadata(self):
#         return {
#             'url': self.config.base_uri,
#         }
# 
#     def get_owner(self, issue):
#         # TODO
#         raise NotImplementedError(
#             "This service has not implemented support for 'only_if_assigned'.")
# 
#     def issues(self):
#         # Construct the whole url by hand here, because otherwise requests will
#         # percent-encode the ':' characters, which gerrit doesn't like.
#         url = self.config.base_uri + '/a/changes/?q=' + self.query_string
#         response = self.session.get(url)
#         response.raise_for_status()
#         # The response has some ")]}'" garbage prefixed.
#         body = response.text[4:]
#         changes = json.loads(body)
# 
#         for change in changes:
#             extra = {
#                 'url': self.build_url(change),
#                 'annotations': self.annotations(change),
#             }
#             yield self.get_issue_for_record(change, extra)
# 
#     def build_url(self, change):
#         return '%s/#/c/%i/' % (self.config.base_uri, change['_number'])
# 
#     def annotations(self, change):
#         entries = []
#         for item in change['messages']:
#             for key in ['name', 'username', 'email']:
#                 if key in item['author']:
#                     username = item['author'][key]
#                     break
#             else:
#                 username = item['author']['_account_id']
#             # Gerrit messages are really messy
#             message = item['message']\
#                 .lstrip('Patch Set ')\
#                 .lstrip("%s:" % item['_revision_number'])\
#                 .strip()\
#                 .replace('\n', ' ')
#             entries.append((username, message,))
# 
#         return self.build_annotations(entries, self.build_url(change))
# 
# Path: tests/base.py
# class ServiceTest(ConfigTest):
#     GENERAL_CONFIG = {
#         'interactive': False,
#         'annotation_length': 100,
#         'description_length': 100,
#     }
#     SERVICE_CONFIG = {
#     }
# 
#     @classmethod
#     def setUpClass(cls):
#         cls.maxDiff = None
# 
#     def get_mock_service(
#         self, service_class, section='unspecified',
#         config_overrides=None, general_overrides=None
#     ):
#         options = {
#             'general': {**self.GENERAL_CONFIG, 'targets': section},
#             section: self.SERVICE_CONFIG.copy(),
#         }
#         if config_overrides:
#             options[section].update(config_overrides)
#         if general_overrides:
#             options['general'].update(general_overrides)
# 
#         service_config = service_class.CONFIG_SCHEMA(**options[section])
#         main_config = schema.MainSectionConfig(**options['general'])
#         main_config.data = data.BugwarriorData(self.lists_path)
# 
#         return service_class(service_config, main_config, section)
# 
#     @staticmethod
#     def add_response(url, **kwargs):
#         responses.add(responses.GET, url, match_querystring=True, **kwargs)
# 
# class AbstractServiceTest(abc.ABC):
#     """ Ensures that certain test methods are implemented for each service. """
#     @abc.abstractmethod
#     def test_to_taskwarrior(self):
#         """ Test Service.to_taskwarrior(). """
#         raise NotImplementedError
# 
#     @abc.abstractmethod
#     def test_issues(self):
#         """
#         Test Service.issues().
# 
#         - When the API is accessed via requests, use the responses library to
#         mock requests.
#         - When the API is accessed via a third party library, substitute a fake
#         implementation class for it.
#         """
#         raise NotImplementedError


# Path: tests/test_gerrit.py
import json
import responses
from bugwarrior.services.gerrit import GerritService
from .base import ServiceTest, AbstractServiceTest




class TestGerritIssue(AbstractServiceTest, ServiceTest):
    SERVICE_CONFIG = {
        'service': 'gerrit',
        'gerrit.base_uri': 'https://one.com',
        'gerrit.username': 'two',
        'gerrit.password': 'three',
    }

    record = {
        'project': 'nova',
        '_number': 1,
        'branch': 'master',
        'topic': 'test-topic',
        'subject': 'this is a title',
        'messages': [{'author': {'username': 'Iam Author'},
                      'message': 'this is a message',
                      '_revision_number': 1}],
    }

    def setUp(self):
        super().setUp()

        responses.add(
            responses.HEAD,
            self.SERVICE_CONFIG['gerrit.base_uri'] + '/a/',
            headers={'www-authenticate': 'digest'})
        with responses.mock:

            self.service = self.get_mock_service(GerritService)