<commit_before>import unittest
import os
import re
import logging
import requests
import json
import urllib3
import urllib
from urllib3_mock import Responses

from phaxio import PhaxioApi
from phaxio.swagger_client.models.phone_number_response import PhoneNumberResponse
from phaxio.swagger_client.models.phone_number import PhoneNumber
from phaxio.swagger_client.api_client import ApiException

# need to set up mocks for both urllib3-based requests (used for most everything) and requests-based ones (used for some posts)
responses_requests = Responses('requests.packages.urllib3')
responses_urllib = Responses()


class PhaxioApiUnitTests(unittest.TestCase):

    logger = logging.getLogger(__name__)
    logger.level = logging.DEBUG

    handler = logging.FileHandler('test.log')
    handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s'))
    logging.getLogger().addHandler(handler)

    def setUp(self):
        self.client = PhaxioApi()
        self.request = None

        # this will cause all API requests to get routed to request_callback, which just returns empty reponses
        # and saves the request in self.request so it can be validated
        url_re = re.compile(r'/v2/.*')
        responses_urllib.add_callback('GET', url_re, callback=self.request_callback)
        responses_urllib.add_callback('POST', url_re, callback=self.request_callback)
        responses_requests.add_callback('POST', url_re, callback=self.request_callback)
        responses_urllib.add_callback('DELETE', url_re, callback=self.request_callback)

    def request_callback(self, r):
        self.request = r
        self.logger.debug('request={}'.format(r))
        return 200, {}, ''

    def assert_request_is_correct(self, method, url, headers_dict=None, body=None):
        self.assertEqual(self.request.method, method)
        self.assertEqual(self.request.url, url)
        if headers_dict:
            self.assertDictContainsSubset(headers_dict, self.request.headers)
        if body:
            self.assertEqual(body, self.request.body)

    @responses_urllib.activate
    @responses_requests.activate
    def test_phone_numbers_api(self):
        self.client.PhoneNumber.get_phone_number_info('4132343233')
        self.assert_request_is_correct('GET', '/v2/phone_numbers/4132343233')

        self.client.PhoneNumber.get_area_codes(page=3, per_page=49)
        self.assert_request_is_correct('GET', '/v2/public/area_codes?per_page=49&page=3')
        # auth not required for this api
        self.assertNotIn('Authorization', self.request.headers)

        # some apis don't like the empty return, so catch the exception
        try:
            self.client.PhoneNumber.provision_phone_number('1', '206', 'http://fake/callback')
        except Exception as e:
            pass

        self.assert_request_is_correct('POST', '/v2/phone_numbers', {'Content-Type': 'application/x-www-form-urlencoded'},
                                       body='country_code=1&area_code=206&callback_url=http%3A%2F%2Ffake%2Fcallback')

        self.client.PhoneNumber.query_phone_numbers(country_code=1, area_code=206, page=4, per_page=12)
        self.assert_request_is_correct('GET', '/v2/phone_numbers?per_page=12&area_code=206&page=4&country_code=1')

        self.client.PhoneNumber.release_phone_number('2065551234')
        self.assert_request_is_correct('DELETE', '/v2/phone_numbers/2065551234')

    @responses_urllib.activate
    @responses_requests.activate
    def test_account_info_api(self):
        self.client.Account.get_status()
        self.assert_request_is_correct('GET', '/v2/account/status')

    @responses_urllib.activate
    @responses_requests.activate
    def test_phax_code_api(self):
        try:
            self.client.PhaxCode.create_json_phax_code('{"test_key": "test_val"}')
        except Exception as e:
            pass

        self.assert_request_is_correct('POST', '/v2/phax_codes',
                                       headers_dict={'Content-Type': 'application/x-www-form-urlencoded'},
                                       body='metadata=%7B%22test_key%22%3A+%22test_val%22%7D')
        self.client.PhaxCode.get_phax_code('phax_code_id')
        self.assert_request_is_correct('GET', '/v2/phax_codes/phax_code_id')

    @responses_urllib.activate
    @responses_requests.activate
    def test_countries_api(self):
        self.client.Countries.get_countries()
        self.assert_request_is_correct('GET', '/v2/public/countries')
        self.client.Countries.get_countries(page=4)
        self.assert_request_is_correct('GET', '/v2/public/countries?page=4')

    @responses_urllib.activate
    @responses_requests.activate
    def test_fax_api(self):
        pass








<commit_msg>unit tests for Fax API<commit_after>import unittest
import os
import re
import logging
import requests
import json
import urllib3
import urllib
from urllib3_mock import Responses
from datetime import datetime

from phaxio import PhaxioApi
from phaxio.swagger_client.models.phone_number_response import PhoneNumberResponse
from phaxio.swagger_client.models.phone_number import PhoneNumber
from phaxio.swagger_client.api_client import ApiException

# need to set up mocks for both urllib3-based requests (used for most everything) and requests-based ones (used for some posts)
responses_requests = Responses('requests.packages.urllib3')
responses_urllib = Responses()


test_phone_number = '2065551234'
test_fax_id = 12345

class PhaxioApiUnitTests(unittest.TestCase):

    logger = logging.getLogger(__name__)
    logger.level = logging.DEBUG

    handler = logging.FileHandler('test.log')
    handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s'))
    logging.getLogger().addHandler(handler)

    def setUp(self):
        self.client = PhaxioApi()
        self.request = None

        # this will cause all API requests to get routed to request_callback, which just returns empty reponses
        # and saves the request in self.request so it can be validated
        url_re = re.compile(r'/v2/.*')
        responses_urllib.add_callback('GET', url_re, callback=self.request_callback)
        responses_urllib.add_callback('POST', url_re, callback=self.request_callback)
        responses_requests.add_callback('POST', url_re, callback=self.request_callback)
        responses_urllib.add_callback('DELETE', url_re, callback=self.request_callback)

    def request_callback(self, r):
        self.request = r
        self.logger.debug('request={}'.format(r))
        return 200, {}, ''

    def assert_request_is_correct(self, method, url, headers_dict=None, body=None):
        self.assertEqual(self.request.method, method)
        self.assertEqual(self.request.url, url)
        if headers_dict:
            self.assertDictContainsSubset(headers_dict, self.request.headers)
        if body:
            self.assertEqual(body, self.request.body)

    @responses_urllib.activate
    @responses_requests.activate
    def test_phone_numbers_api(self):
        self.client.PhoneNumber.get_phone_number_info(test_phone_number)
        self.assert_request_is_correct('GET', '/v2/phone_numbers/{}'.format(test_phone_number))

        self.client.PhoneNumber.get_area_codes(page=3, per_page=49)
        self.assert_request_is_correct('GET', '/v2/public/area_codes?per_page=49&page=3')
        # auth not required for this api
        self.assertNotIn('Authorization', self.request.headers)

        # some apis don't like the empty return, so catch the exception
        try:
            self.client.PhoneNumber.provision_phone_number('1', '206', 'http://fake/callback')
        except Exception as e:
            pass

        self.assert_request_is_correct('POST', '/v2/phone_numbers', {'Content-Type': 'application/x-www-form-urlencoded'},
                                       body='country_code=1&area_code=206&callback_url=http%3A%2F%2Ffake%2Fcallback')

        self.client.PhoneNumber.query_phone_numbers(country_code=1, area_code=206, page=4, per_page=12)
        self.assert_request_is_correct('GET', '/v2/phone_numbers?per_page=12&area_code=206&page=4&country_code=1')

        self.client.PhoneNumber.release_phone_number(test_phone_number)
        self.assert_request_is_correct('DELETE', '/v2/phone_numbers/{}'.format(test_phone_number))

    @responses_urllib.activate
    @responses_requests.activate
    def test_account_info_api(self):
        self.client.Account.get_status()
        self.assert_request_is_correct('GET', '/v2/account/status')

    @responses_urllib.activate
    @responses_requests.activate
    def test_phax_code_api(self):
        try:
            self.client.PhaxCode.create_json_phax_code('{"test_key": "test_val"}')
        except Exception as e:
            pass

        self.assert_request_is_correct('POST', '/v2/phax_codes',
                                       headers_dict={'Content-Type': 'application/x-www-form-urlencoded'},
                                       body='metadata=%7B%22test_key%22%3A+%22test_val%22%7D')
        self.client.PhaxCode.get_phax_code('phax_code_id')
        self.assert_request_is_correct('GET', '/v2/phax_codes/phax_code_id')

    @responses_urllib.activate
    @responses_requests.activate
    def test_countries_api(self):
        self.client.Countries.get_countries()
        self.assert_request_is_correct('GET', '/v2/public/countries')
        self.client.Countries.get_countries(page=4)
        self.assert_request_is_correct('GET', '/v2/public/countries?page=4')

    @responses_urllib.activate
    @responses_requests.activate
    def test_fax_api(self):
        self.client.Fax.cancel(test_fax_id)
        self.assert_request_is_correct('POST', '/v2/faxes/{}/cancel'.format(test_fax_id))

        self.client.Fax.resend(test_fax_id)
        self.assert_request_is_correct('POST', '/v2/faxes/{}/resend'.format(test_fax_id))

        self.client.Fax.delete(test_fax_id)
        self.assert_request_is_correct('DELETE', '/v2/faxes/{}'.format(test_fax_id))

        self.client.Fax.delete_file(test_fax_id)
        self.assert_request_is_correct('DELETE', '/v2/faxes/{}/file'.format(test_fax_id))

        self.client.Fax.status(test_fax_id)
        self.assert_request_is_correct('GET', '/v2/faxes/{}'.format(test_fax_id))

        self.client.Fax.get_file(test_fax_id)
        self.assert_request_is_correct('GET', '/v2/faxes/{}/file'.format(test_fax_id),
                                       headers_dict={'Accept': 'application/octet-stream'})

        self.client.Fax.get_file(test_fax_id, thumbnail='l')
        self.assert_request_is_correct('GET', '/v2/faxes/{}/file?thumbnail=l'.format(test_fax_id),
                                       headers_dict={'Accept': 'application/octet-stream'})
        timestamp = datetime.now().replace(microsecond=0)
        ts_str = timestamp.isoformat('T')
        ts_str_encoded = urllib.quote_plus(ts_str)

        # send timestamp as datetime object
        self.client.Fax.query_faxes(created_before=timestamp, created_after=timestamp, direction='send',
                                    status='success', phone_number=test_phone_number, per_page=2, page=1)
        self.assert_request_is_correct('GET', '/v2/faxes?status=success&phone_number=2065551234&direction=send&'
                                       'created_after={}&per_page=2&created_before={}&page=1'.format(ts_str_encoded, ts_str_encoded))
        # send timestamp as string
        self.client.Fax.query_faxes(created_before=ts_str, created_after=ts_str)
        self.assert_request_is_correct('GET',
                                       '/v2/faxes?created_before={}&created_after={}'.format(ts_str_encoded, ts_str_encoded))

    @responses_urllib.activate
    @responses_requests.activate
    def test_send_fax(self):
        try:
            self.client.Fax.send(test_phone_number, content_urls=['http://www.google.com', 'http://www.bing.com'],
                             header_text='foo header text', batch_delay=10, batch_collision_avoidance=True,
                             callback_url='http://a.callback.url.com', cancel_timeout='30', caller_id=test_phone_number,
                             test_fail=False)
        except Exception as e:
            pass

        self.assert_request_is_correct('POST', '/v2/faxes', {'Content-Type': 'application/x-www-form-urlencoded'})
        body = urllib.unquote_plus(self.request.body)
        actual_vals = body.split('&')
        correct_vals = ['to={}'.format(test_phone_number), 'caller_id={}'.format(test_phone_number),
                        'content_url[]=http://www.google.com', 'content_url[]=http://www.bing.com',
                        'header_text=foo header text', 'batch_delay=10', 'batch_collision_avoidance=true',
                        'callback_url=http://a.callback.url.com', 'cancel_timeout=30', 'test_fail=false'
        ]
        actual_vals.sort()
        correct_vals.sort()
        self.assertListEqual(actual_vals, correct_vals)

        with open('./_test_fax_file1.pdf', mode='w+') as file:
            file.write('test file 1 contents')

        with open('./_test_fax_file2.doc', mode='w+') as file:
            file.write('test file 2 contents')
        try:
            self.client.Fax.send(test_phone_number, files=['./_test_fax_file1.pdf', './_test_fax_file2.doc'],
                                 content_urls=['http://www.google.com', 'http://www.bing.com'])
        except Exception as e:
            pass
        self.assert_request_is_correct('POST', '/v2/faxes')
        # find the delimiter in the header, split up the body by the delimiter, then verify that each value is correct
        self.assertTrue(self.request.headers['Content-Type'].startswith('multipart/form-data'))
        delim = '--' + self.request.headers['Content-Type'].split('=')[-1]
        self.logger.debug('delim={}'.format(delim))
        body_lst = re.split('\s*{}-*\s*'.format(delim), self.request.body)
        body_lst = [x for x in body_lst if x]  # remove empty strings from list
        self.logger.debug('body_lst={}'.format(body_lst))
        correct_vals = ['Content-Disposition: form-data; name="to"\r\n\r\n2065551234',
                        'Content-Disposition: form-data; name="content_url[]"\r\n\r\nhttp://www.google.com',
                        'Content-Disposition: form-data; name="content_url[]"\r\n\r\nhttp://www.bing.com',
                        'Content-Disposition: form-data; name="file[]"; filename="_test_fax_file1.pdf"\r\nContent-Type: application/pdf\r\n\r\ntest file 1 contents',
                        'Content-Disposition: form-data; name="file[]"; filename="_test_fax_file2.doc"\r\nContent-Type: application/msword\r\n\r\ntest file 2 contents',
                        ]
        correct_vals.sort()
        body_lst.sort()
        self.assertListEqual(body_lst, correct_vals)
{'fraction_non_alphanumeric': 0.12005630781606114, 'fraction_numerical': 0.01581981498860437, 'mean_word_length': 3.1801625105071447, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 13, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6302171', 'n_tokens_mistral': 4841, 'n_tokens_neox': 4622, 'n_words': 701}