<commit_before>import responses
import requests
from urllib.parse import urljoin
# import json

from django.core.cache import cache
from django.test import TestCase

from .. import api

from . import fixtures
from . import mocks as mk

from djconnectwise.api import ConnectWiseAPIError, ConnectWiseAPIClientError
from djconnectwise.api import ConnectWiseRecordNotFoundError
from djconnectwise.api import CompanyInfoManager


API_URL = 'https://localhost/v4_6_release/apis/3.0/system/members/count'


class BaseAPITestCase(TestCase):

    def assert_request_should_page(self, should_page):
        request_url = responses.calls[0].request.url
        params = ['pageSize=1000', 'page=1']

        if should_page:
            for param in params:
                self.assertIn(param, request_url)
        else:
            for param in params:
                self.assertNotIn(param, request_url)


class TestConnectWiseAPIClient(TestCase):
    def setUp(self):
        self.client = api.ServiceAPIClient()  # Must use a real client as
        # ConnectWiseAPIClient is effectively abstract

    def test_prepare_conditions_single(self):
        conditions = [
            'closedFlag = False',
        ]
        self.assertEqual(
            self.client.prepare_conditions(conditions),
            '(closedFlag = False)'
        )

    def test_prepare_conditions_multiple(self):
        conditions = [
            'closedFlag = False',
            'status/id in (1,2,3)',
        ]
        self.assertEqual(
            self.client.prepare_conditions(conditions),
            '(closedFlag = False and status/id in (1,2,3))'
        )

    @responses.activate
    def test_request(self):
        endpoint = 'http://example.com/'
        response = 'ok'
        responses.add(responses.GET, endpoint, json=response, status=200)

        result = self.client.request('get', endpoint, None)
        self.assertEqual(result, response)

    @responses.activate
    def test_request_failure(self):
        endpoint = 'http://example.com/'
        responses.add(
            responses.GET, endpoint, body=requests.RequestException()
        )

        with self.assertRaises(ConnectWiseAPIError):
            self.client.request('get', endpoint, None)

    @responses.activate
    def test_request_400(self):
        endpoint = 'http://example.com/'
        response = {'error': 'this is bad'}
        responses.add(responses.GET, endpoint, json=response, status=400)

        with self.assertRaises(ConnectWiseAPIError):
            self.client.request('get', endpoint, None)


class TestServiceAPIClient(BaseAPITestCase):

    def setUp(self):
        self.client = api.ServiceAPIClient()

    def _get_boards_stub(self, return_value):
        endpoint = self.client._endpoint(self.client.ENDPOINT_BOARDS)
        return mk.get(endpoint, return_value)

    @responses.activate
    def test_get_boards(self):
        self._get_boards_stub(fixtures.API_BOARD_LIST)

        result = self.client.get_boards()
        self.assertEqual(result, fixtures.API_BOARD_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_boards_no_data(self):
        return_value = {}
        self._get_boards_stub(return_value)

        result = self.client.get_boards()
        self.assertEqual(result, return_value)

    @responses.activate
    def test_get_statuses(self):
        endpoint_url = 'boards/{}/statuses'.format(
            fixtures.API_BOARD['id'])

        endpoint_url = self.client._endpoint(endpoint_url)

        mk.get(endpoint_url, fixtures.API_BOARD_STATUS_LIST)

        result = self.client.get_statuses(fixtures.API_BOARD['id'])
        self.assertEqual(result, fixtures.API_BOARD_STATUS_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_priorities(self):
        endpoint_url = self.client._endpoint(self.client.ENDPOINT_PRIORITIES)
        mk.get(endpoint_url, fixtures.API_SERVICE_PRIORITY_LIST)

        result = self.client.get_priorities()
        self.assertEqual(result, fixtures.API_SERVICE_PRIORITY_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_teams(self):
        board_id = fixtures.API_BOARD_LIST[0]['id']
        endpoint = '{}/{}/teams/'.format(self.client.ENDPOINT_BOARDS, board_id)
        endpoint_url = self.client._endpoint(endpoint)
        mk.get(endpoint_url, fixtures.API_SERVICE_TEAM_LIST)
        result = self.client.get_teams(board_id)
        self.assertEqual(result, fixtures.API_SERVICE_TEAM_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_locations(self):
        endpoint_url = self.client._endpoint(self.client.ENDPOINT_LOCATIONS)
        mk.get(endpoint_url, fixtures.API_SERVICE_LOCATION_LIST)

        result = self.client.get_locations()
        self.assertEqual(result, fixtures.API_SERVICE_LOCATION_LIST)
        self.assert_request_should_page(True)


class TestSystemAPIClient(BaseAPITestCase):

    def setUp(self):
        self.client = api.SystemAPIClient()

    @responses.activate
    def test_get_connectwise_version(self):
        endpoint = self.client._endpoint(self.client.ENDPOINT_INFO)
        mk.get(endpoint,
               fixtures.API_CW_VERSION)
        result = self.client.get_connectwise_version()
        self.assertEqual(result, fixtures.API_CW_VERSION['version'])
        self.assert_request_should_page(False)

    @responses.activate
    def test_get_members(self):
        endpoint = self.client._endpoint(self.client.ENDPOINT_MEMBERS_COUNT)
        mk.get(endpoint,
               fixtures.API_MEMBER_COUNT)

        endpoint = self.client._endpoint(self.client.ENDPOINT_MEMBERS)
        mk.get(endpoint,
               fixtures.API_MEMBER_LIST)

        result = self.client.get_members()
        self.assertEqual(result, fixtures.API_MEMBER_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_member_image_by_identifier(self):
        member = fixtures.API_MEMBER
        # Requests will fake returning this as the filename
        avatar = mk.get_member_avatar()
        avatar_filename = 'AnonymousMember.png'
        endpoint = self.client._endpoint(
            self.client.ENDPOINT_MEMBERS_IMAGE.format(member['identifier']))
        mk.get_raw(
            endpoint,
            avatar,
            headers={
                'content-disposition':
                    'attachment; filename={}'.format(avatar_filename),
            }
        )

        result_filename, result_avatar = self.client \
            .get_member_image_by_identifier(member['identifier'])

        self.assertEqual(result_filename, avatar_filename)
        self.assertEqual(result_avatar, avatar)

    def test_attachment_filename_returns_filename(self):
        # It works with a file extension
        self.assertEqual(
            self.client._attachment_filename(
                'attachment; filename=somefile.jpg'
            ),
            'somefile.jpg',
        )
        # It also works without a file extension
        self.assertEqual(
            self.client._attachment_filename('attachment; filename=somefile'),
            'somefile',
        )
        # It also works with a space and quoted filename
        self.assertEqual(
            self.client._attachment_filename(
                'attachment; filename="somefile and a space.jpg"'
            ),
            'somefile and a space.jpg',
        )
        # And it works with Unicode
        filename = 'attachment; filename=Ƨōmefile.jpg'
        self.assertEqual(
            self.client._attachment_filename(filename),
            'Ƨōmefile.jpg',
        )

    def test_attachment_filename_returns_none_on_invalid(self):
        self.assertEqual(
            self.client._attachment_filename(''),
            None,
        )


class TestProjectAPIClient(BaseAPITestCase):
    def setUp(self):
        self.client = api.ProjectAPIClient()

    @responses.activate
    def test_get_projects(self):
        endpoint = self.client._endpoint(self.client.ENDPOINT_PROJECTS)
        mk.get(endpoint, fixtures.API_PROJECT_LIST)

        result = self.client.get_projects()

        self.assertIsNotNone(result)
        self.assert_request_should_page(True)


class TestCompanyAPIClient(BaseAPITestCase):

    def setUp(self):
        super(TestCompanyAPIClient, self).setUp()
        self.client = api.CompanyAPIClient()
        self.endpoint = self.client._endpoint(self.client.ENDPOINT_COMPANIES)

    @responses.activate
    def test_by_id(self):
        company_id = fixtures.API_COMPANY['id']
        endpoint_url = '{}/{}'.format(self.endpoint, company_id)

        mk.get(endpoint_url,
               fixtures.API_COMPANY)
        result = self.client.by_id(company_id)
        self.assertEqual(result, fixtures.API_COMPANY)
        self.assert_request_should_page(False)

    @responses.activate
    def test_get(self):
        mk.get(self.endpoint,
               fixtures.API_COMPANY_LIST)
        result = self.client.get_companies()
        self.assertEqual(len(result), len(fixtures.API_COMPANY_LIST))
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_no_results(self):
        data = {}
        mk.get(self.endpoint,
               data)
        result = self.client.get_companies()

        self.assertEqual(result, data)

    @responses.activate
    def test_get_company_statuses(self):
        endpoint = self.client._endpoint(
            self.client.ENDPOINT_COMPANY_STATUSES)

        mk.get(endpoint, fixtures.API_COMPANY_STATUS_LIST)
        result = self.client.get_company_statuses()
        self.assertEqual(result, fixtures.API_COMPANY_STATUS_LIST)
        self.assert_request_should_page(True)


class TestFetchAPICodebase(TestCase):
    HOST = 'https://na.myconnectwise.net'

    def setUp(self):
        self.manager = CompanyInfoManager()

    def _some_end_point(self):
        return urljoin(self.HOST, 'some-endpoint')

    def test_fetch_api_codebase_bad_url(self):
        api_codebase, updated = self.manager.fetch_api_codebase('')
        self.assertEqual(api_codebase,
                         api.DEFAULT_CW_API_CODEBASE)

    @responses.activate
    def test_fetch_api_company_info_endpoint_unavailable(self):
        mk.get(urljoin(self.HOST, api.CompanyInfoManager.COMPANYINFO_PATH),<commit_msg>WIP: start test_api code<commit_after>import responses
import requests
from urllib.parse import urljoin
# import json

from django.core.cache import cache
from django.test import TestCase

from .. import api

from . import fixtures
from . import mocks as mk

from djconnectwise.api import ConnectWiseAPIError, ConnectWiseAPIClientError
from djconnectwise.api import ConnectWiseRecordNotFoundError
from djconnectwise.api import CompanyInfoManager


API_URL = 'https://localhost/v4_6_release/apis/3.0/system/members/count'


class BaseAPITestCase(TestCase):

    def assert_request_should_page(self, should_page):
        request_url = responses.calls[0].request.url
        params = ['pageSize=1000', 'page=1']

        if should_page:
            for param in params:
                self.assertIn(param, request_url)
        else:
            for param in params:
                self.assertNotIn(param, request_url)


class TestConnectWiseAPIClient(TestCase):
    def setUp(self):
        self.client = api.ServiceAPIClient()  # Must use a real client as
        # ConnectWiseAPIClient is effectively abstract

    def test_prepare_conditions_single(self):
        conditions = [
            'closedFlag = False',
        ]
        self.assertEqual(
            self.client.prepare_conditions(conditions),
            '(closedFlag = False)'
        )

    def test_prepare_conditions_multiple(self):
        conditions = [
            'closedFlag = False',
            'status/id in (1,2,3)',
        ]
        self.assertEqual(
            self.client.prepare_conditions(conditions),
            '(closedFlag = False and status/id in (1,2,3))'
        )

    @responses.activate
    def test_request(self):
        endpoint = 'http://example.com/'
        response = 'ok'
        responses.add(responses.GET, endpoint, json=response, status=200)

        result = self.client.request('get', endpoint, None)
        self.assertEqual(result, response)

    @responses.activate
    def test_request_failure(self):
        endpoint = 'http://example.com/'
        responses.add(
            responses.GET, endpoint, body=requests.RequestException()
        )

        with self.assertRaises(ConnectWiseAPIError):
            self.client.request('get', endpoint, None)

    @responses.activate
    def test_request_400(self):
        endpoint = 'http://example.com/'
        response = {'error': 'this is bad'}
        responses.add(responses.GET, endpoint, json=response, status=400)

        with self.assertRaises(ConnectWiseAPIError):
            self.client.request('get', endpoint, None)


class TestServiceAPIClient(BaseAPITestCase):

    def setUp(self):
        self.client = api.ServiceAPIClient()

    def _get_boards_stub(self, return_value):
        endpoint = self.client._endpoint(self.client.ENDPOINT_BOARDS)
        return mk.get(endpoint, return_value)

    @responses.activate
    def test_get_boards(self):
        self._get_boards_stub(fixtures.API_BOARD_LIST)

        result = self.client.get_boards()
        self.assertEqual(result, fixtures.API_BOARD_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_boards_no_data(self):
        return_value = {}
        self._get_boards_stub(return_value)

        result = self.client.get_boards()
        self.assertEqual(result, return_value)

    @responses.activate
    def test_get_statuses(self):
        endpoint_url = 'boards/{}/statuses'.format(
            fixtures.API_BOARD['id'])

        endpoint_url = self.client._endpoint(endpoint_url)

        mk.get(endpoint_url, fixtures.API_BOARD_STATUS_LIST)

        result = self.client.get_statuses(fixtures.API_BOARD['id'])
        self.assertEqual(result, fixtures.API_BOARD_STATUS_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_priorities(self):
        endpoint_url = self.client._endpoint(self.client.ENDPOINT_PRIORITIES)
        mk.get(endpoint_url, fixtures.API_SERVICE_PRIORITY_LIST)

        result = self.client.get_priorities()
        self.assertEqual(result, fixtures.API_SERVICE_PRIORITY_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_teams(self):
        board_id = fixtures.API_BOARD_LIST[0]['id']
        endpoint = '{}/{}/teams/'.format(self.client.ENDPOINT_BOARDS, board_id)
        endpoint_url = self.client._endpoint(endpoint)
        mk.get(endpoint_url, fixtures.API_SERVICE_TEAM_LIST)
        result = self.client.get_teams(board_id)
        self.assertEqual(result, fixtures.API_SERVICE_TEAM_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_locations(self):
        endpoint_url = self.client._endpoint(self.client.ENDPOINT_LOCATIONS)
        mk.get(endpoint_url, fixtures.API_SERVICE_LOCATION_LIST)

        result = self.client.get_locations()
        self.assertEqual(result, fixtures.API_SERVICE_LOCATION_LIST)
        self.assert_request_should_page(True)


class TestSystemAPIClient(BaseAPITestCase):

    def setUp(self):
        self.client = api.SystemAPIClient()

    @responses.activate
    def test_get_connectwise_version(self):
        endpoint = self.client._endpoint(self.client.ENDPOINT_INFO)
        mk.get(endpoint,
               fixtures.API_CW_VERSION)
        result = self.client.get_connectwise_version()
        self.assertEqual(result, fixtures.API_CW_VERSION['version'])
        self.assert_request_should_page(False)

    @responses.activate
    def test_get_members(self):
        endpoint = self.client._endpoint(self.client.ENDPOINT_MEMBERS_COUNT)
        mk.get(endpoint,
               fixtures.API_MEMBER_COUNT)

        endpoint = self.client._endpoint(self.client.ENDPOINT_MEMBERS)
        mk.get(endpoint,
               fixtures.API_MEMBER_LIST)

        result = self.client.get_members()
        self.assertEqual(result, fixtures.API_MEMBER_LIST)
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_member_image_by_identifier(self):
        member = fixtures.API_MEMBER
        # Requests will fake returning this as the filename
        avatar = mk.get_member_avatar()
        avatar_filename = 'AnonymousMember.png'
        endpoint = self.client._endpoint(
            self.client.ENDPOINT_MEMBERS_IMAGE.format(member['identifier']))
        mk.get_raw(
            endpoint,
            avatar,
            headers={
                'content-disposition':
                    'attachment; filename={}'.format(avatar_filename),
            }
        )

        result_filename, result_avatar = self.client \
            .get_member_image_by_identifier(member['identifier'])

        self.assertEqual(result_filename, avatar_filename)
        self.assertEqual(result_avatar, avatar)

    def test_attachment_filename_returns_filename(self):
        # It works with a file extension
        self.assertEqual(
            self.client._attachment_filename(
                'attachment; filename=somefile.jpg'
            ),
            'somefile.jpg',
        )
        # It also works without a file extension
        self.assertEqual(
            self.client._attachment_filename('attachment; filename=somefile'),
            'somefile',
        )
        # It also works with a space and quoted filename
        self.assertEqual(
            self.client._attachment_filename(
                'attachment; filename="somefile and a space.jpg"'
            ),
            'somefile and a space.jpg',
        )
        # And it works with Unicode
        filename = 'attachment; filename=Ƨōmefile.jpg'
        self.assertEqual(
            self.client._attachment_filename(filename),
            'Ƨōmefile.jpg',
        )

    def test_attachment_filename_returns_none_on_invalid(self):
        self.assertEqual(
            self.client._attachment_filename(''),
            None,
        )


class TestProjectAPIClient(BaseAPITestCase):
    def setUp(self):
        self.client = api.ProjectAPIClient()

    @responses.activate
    def test_get_projects(self):
        endpoint = self.client._endpoint(self.client.ENDPOINT_PROJECTS)
        mk.get(endpoint, fixtures.API_PROJECT_LIST)

        result = self.client.get_projects()

        self.assertIsNotNone(result)
        self.assert_request_should_page(True)


class TestCompanyAPIClient(BaseAPITestCase):

    def setUp(self):
        super(TestCompanyAPIClient, self).setUp()
        self.client = api.CompanyAPIClient()
        self.endpoint = self.client._endpoint(self.client.ENDPOINT_COMPANIES)

    @responses.activate
    def test_by_id(self):
        company_id = fixtures.API_COMPANY['id']
        endpoint_url = '{}/{}'.format(self.endpoint, company_id)

        mk.get(endpoint_url,
               fixtures.API_COMPANY)
        result = self.client.by_id(company_id)
        self.assertEqual(result, fixtures.API_COMPANY)
        self.assert_request_should_page(False)

    @responses.activate
    def test_get(self):
        mk.get(self.endpoint,
               fixtures.API_COMPANY_LIST)
        result = self.client.get_companies()
        self.assertEqual(len(result), len(fixtures.API_COMPANY_LIST))
        self.assert_request_should_page(True)

    @responses.activate
    def test_get_no_results(self):
        data = {}
        mk.get(self.endpoint,
               data)
        result = self.client.get_companies()

        self.assertEqual(result, data)

    @responses.activate
    def test_get_company_statuses(self):
        endpoint = self.client._endpoint(
            self.client.ENDPOINT_COMPANY_STATUSES)

        mk.get(endpoint, fixtures.API_COMPANY_STATUS_LIST)
        result = self.client.get_company_statuses()
        self.assertEqual(result, fixtures.API_COMPANY_STATUS_LIST)
        self.assert_request_should_page(True)


class TestScheduleAPIClient(BaseAPITestCase):

    def setUp(self):
        super(TestScheduleAPIClient, self).setUp()
        self.client = api.ScheduleAPIClient()
        self.endpoint = self.client._endpoint(self.client.ENDPOINT_ENTRIES)




class TestFetchAPICodebase(TestCase):
    HOST = 'https://na.myconnectwise.net'

    def setUp(self):
        self.manager = CompanyInfoManager()

    def _some_end_point(self):
        return urljoin(self.HOST, 'some-endpoint')

    def test_fetch_api_codebase_bad_url(self):
        api_codebase, updated = self.manager.fetch_api_codebase('')
        self.assertEqual(api_codebase,
                         api.DEFAULT_CW_API_CODEBASE)

    @responses.activate
    def test_fetch_api_company_info_endpoint_unavailable(self):
        mk.get(urljoin(self.HOST, api.CompanyInfoManager.COMPANYINFO_PATH),
{'fraction_non_alphanumeric': 0.09333206867115622, 'fraction_numerical': 0.002466091245376079, 'mean_word_length': 2.7488, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2206909', 'n_tokens_mistral': 6259, 'n_tokens_neox': 6118, 'n_words': 966}