def setUp(self): self.api_key = "dummy_key" self.betamax_record = "none" if os.environ.get("BESNAPPY_TEST_RECORD_REQUESTS"): if BESNAPPY_TEST_API_KEY: self.betamax_record = "all" self.api_key = BESNAPPY_TEST_API_KEY else: raise RuntimeError( "BESNAPPY_TEST_RECORD_REQUESTS is set, but" " BESNAPPY_TEST_API_KEY is not.") self.no_http_session = TestSession() self.betamax_session = Session() # We reset the Accept-Encoding header to avoid storing (opaque) gzip # response data. self.betamax_session.headers["Accept-Encoding"] = "" self.betamax = Betamax( self.betamax_session, cassette_library_dir=CASSETTE_LIBRARY_DIR) self.common_session = Session() # We reset the Accept-Encoding header to avoid storing (opaque) gzip # response data. self.common_session.headers["Accept-Encoding"] = "" self.betamax_common = Betamax( self.common_session, cassette_library_dir=CASSETTE_LIBRARY_DIR) self.betamax_placeholders = [] self.common_snappy = self._get_common_snappy()
def test_creates_new_cassettes(self): recorder = Betamax(self.session) opts = {'record': 'new_episodes'} cassette_name = 'test_record_new_makes_new_cassettes' with recorder.use_cassette(cassette_name, **opts) as betamax: self.cassette_path = betamax.current_cassette.cassette_path self.session.get('https://httpbin.org/get')
def test_creates_new_cassettes(self): recorder = Betamax(self.session) opts = {"record": "new_episodes"} cassette_name = "test_record_new_makes_new_cassettes" with recorder.use_cassette(cassette_name, **opts) as betamax: self.cassette_path = betamax.current_cassette.cassette_path self.session.get("https://httpbin.org/get")
def test_register_request_matcher(self): class FakeMatcher(object): name = 'fake' Betamax.register_request_matcher(FakeMatcher) assert 'fake' in matchers.matcher_registry assert isinstance(matchers.matcher_registry['fake'], FakeMatcher)
class TestBetamax(unittest.TestCase): def setUp(self): self.session = Session() self.vcr = Betamax(self.session) def test_initialization_does_alter_the_session(self): for v in self.session.adapters.values(): assert not isinstance(v, BetamaxAdapter) assert isinstance(v, HTTPAdapter) def test_entering_context_alters_adapters(self): with self.vcr: for v in self.session.adapters.values(): assert isinstance(v, BetamaxAdapter) def test_exiting_resets_the_adapters(self): with self.vcr: pass for v in self.session.adapters.values(): assert not isinstance(v, BetamaxAdapter) def test_current_cassette(self): assert self.vcr.current_cassette is None self.vcr.use_cassette('test') assert isinstance(self.vcr.current_cassette, Cassette) def test_use_cassette_returns_cassette_object(self): assert self.vcr.use_cassette('test') is self.vcr def test_register_request_matcher(self): class FakeMatcher(object): name = 'fake' Betamax.register_request_matcher(FakeMatcher) assert 'fake' in matchers.matcher_registry assert isinstance(matchers.matcher_registry['fake'], FakeMatcher) def test_stores_the_session_instance(self): assert self.session is self.vcr.session def test_replaces_all_adapters(self): mount_point = 'fake_protocol://' s = Session() s.mount(mount_point, HTTPAdapter()) with Betamax(s): adapter = s.adapters.get(mount_point) assert adapter is not None assert isinstance(adapter, BetamaxAdapter)
def setUpClass(cls): cls.session = requests.Session() cls.recorder = Betamax(cls.session) cls.api_key = config.MAILCHIMP_API_KEY # the subdomain to use in the api url # is always the last 3 characters of the api key cls.subdomain = cls.api_key[-3:] # define the string that will be passed in the MailChimp request # 'Authorization' header MAILCHIMP_REQUEST_AUTH_HEADER_NAME = 'apikey' MAILCHIMP_REQUEST_AUTH_HEADER = '{}:{}'.format( MAILCHIMP_REQUEST_AUTH_HEADER_NAME, cls.api_key) # create the directory to store betamax cassettes abs_cassette_dir = os.path.join(os.path.dirname( os.path.abspath(__file__)), cls.cassette_dir) os.makedirs(abs_cassette_dir, exist_ok=True) Betamax.register_serializer(pretty_json.PrettyJSONSerializer) with Betamax.configure() as betamaxconfig: betamaxconfig.cassette_library_dir = abs_cassette_dir betamaxconfig.default_cassette_options['record_mode'] = 'once' betamaxconfig.default_cassette_options[ 'serialize_with'] = 'prettyjson' betamaxconfig.default_cassette_options['match_requests_on'] = [ 'method' ] betamaxconfig.define_cassette_placeholder( '<MAILCHIMP_AUTH_B64>', base64.b64encode( MAILCHIMP_REQUEST_AUTH_HEADER.encode() ).decode() ) betamaxconfig.define_cassette_placeholder( '<MAILCHIMP_SUBDOMAIN>', cls.subdomain ) # suppress these warnings (due to requests module): # ResourceWarning: unclosed <ssl.SSLSocket warnings.simplefilter("ignore", ResourceWarning)
def setup(self): self.lat = 51.0 + 32.0/60.0 self.lng = -22.0/60.0 self.year = 2015 self.usno_data = USNO_Data(self.lat, self.lng) self.recorder = Betamax(self.usno_data.session, default_cassette_options={ 'record_mode': 'once', 'match_requests_on': ['method', 'uri', 'headers'], 'preserve_exact_body_bytes': True })
def helium_recorder(request): """Generate and start a recorder using a helium.Client.""" cassette_name = '' if request.module is not None: cassette_name += request.module.__name__ + '.' if request.cls is not None: cassette_name += request.cls.__name__ + '.' cassette_name += request.function.__name__ session = helium_commander.Client(base_url=API_URL) session.token_auth(API_TOKEN) recorder = Betamax(session) recorder.use_cassette(cassette_name) recorder.start() request.addfinalizer(recorder.stop) return recorder
def test_preserve_exact_body_bytes(self): with Betamax.configure() as config: config.preserve_exact_body_bytes = True with Betamax(self.session) as b: b.use_cassette('global_preserve_exact_body_bytes') r = self.session.get('https://httpbin.org/get') assert 'headers' in r.json() interaction = b.current_cassette.interactions[0].json assert 'base64_string' in interaction['response']['body']
def configure(): config = Betamax.configure() config.cassette_library_dir = "tests/test_api/betamax/" config.default_cassette_options['record_mode'] = 'once' config.default_cassette_options['match_requests_on'] = ['method', 'path_matcher'] if credentials: auth_key = 'token' if 'token' in credentials else 'password' config.define_cassette_placeholder( '<ZENPY-CREDENTIALS>', str(base64.b64encode( "{}/token:{}".format(credentials['email'], credentials[auth_key]).encode('utf-8') )) ) session = requests.Session() credentials['session'] = session zenpy_client = Zenpy(**credentials) recorder = Betamax(session=session) class PathMatcher(URIMatcher): """ I use trial accounts for testing Zenpy and as such the subdomain is always changing. This matcher ignores the netloc section of the parsed URL which prevents the tests failing when the subdomain is changed. """ name = 'path_matcher' def parse(self, uri): parse_result = super(PathMatcher, self).parse(uri) parse_result.pop('netloc') return parse_result Betamax.register_request_matcher(PathMatcher) recorder.register_serializer(PrettyJSONSerializer) return zenpy_client, recorder
def test_revoke__refresh_token_without_access_set(self): authorizer = prawcore.Authorizer( self.authentication, refresh_token=REFRESH_TOKEN ) with Betamax(REQUESTOR).use_cassette( "Authorizer_revoke__refresh_token_without_access_set" ): authorizer.revoke() self.assertIsNone(authorizer.access_token) self.assertIsNone(authorizer.refresh_token) self.assertIsNone(authorizer.scopes) self.assertFalse(authorizer.is_valid())
def test_revoke__access_token_without_refresh_set(self): self.authentication.redirect_uri = REDIRECT_URI authorizer = prawcore.Authorizer(self.authentication) with Betamax(REQUESTOR).use_cassette( "Authorizer_revoke__access_token_without_refresh_set" ): authorizer.authorize(TEMPORARY_GRANT_CODE) authorizer.revoke() self.assertIsNone(authorizer.access_token) self.assertIsNone(authorizer.refresh_token) self.assertIsNone(authorizer.scopes) self.assertFalse(authorizer.is_valid())
def test_payments_can_delete(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('payments/delete') payment = self.client.payments.retrieve(TestPayments.paymentId) assert payment is not None payment.delete() with pytest.raises(NotFoundError) as excinfo: payment = self.client.payments.retrieve(TestPayments.paymentId) raise Exception('Should raise exception') assert True
def test_payments_can_update(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('payments/update') payment = self.client.payments.retrieve(TestPayments.paymentId) assert payment is not None payment.amount = "1200" payment.update() assert payment.amount == "1200" payment = self.client.payments.retrieve(TestPayments.paymentId) assert payment is not None assert payment.amount == "1200.00"
def test_fiction_spider_parse(self): request = next(self.spider.start_requests()) with Betamax(self.session) as vcr: vcr.use_cassette('parse') resp = self.session.get(request.url, headers=self.headers) selector = HtmlResponse(body=resp.content, url=request.url, request=request) for request in self.spider.parse(selector): if isinstance(request, FictionItem): assert request.check() else: assert match_url(request.url, FICTION_URL_PATTEN) assert request.priority == FICTION_PRIORITY
def test_replays_response_from_cassette(self): s = self.session with Betamax(s).use_cassette('test_replays_response') as betamax: self.cassette_path = betamax.current_cassette.cassette_path assert betamax.current_cassette.is_empty() is True r0 = s.get('http://httpbin.org/get') assert r0.status_code == 200 assert betamax.current_cassette.interactions != [] assert len(betamax.current_cassette.interactions) == 1 r1 = s.get('http://httpbin.org/get') assert len(betamax.current_cassette.interactions) == 1 assert r1.status_code == 200 assert r0.headers == r1.headers assert r0.content == r1.content
def test_request__post(self): with Betamax(REQUESTOR).use_cassette("Session_request__post"): session = prawcore.Session(script_authorizer()) data = { "kind": "self", "sr": "reddit_api_test", "text": "Test!", "title": "A Test from PRAWCORE.", } key_count = len(data) response = session.request("POST", "/api/submit", data=data) self.assertIn("a_test_from_prawcore", response["json"]["data"]["url"]) self.assertEqual(key_count, len(data)) # Ensure data is untouched
def test_preserve_exact_body_bytes_does_not_munge_response_content(self): # Do not delete this cassette after the test self.cassette_created = False with Betamax(self.session) as b: b.use_cassette('preserve_exact_bytes', preserve_exact_body_bytes=True, match_requests_on=['uri', 'method', 'body']) r = self.session.post('https://httpbin.org/post', data={'a': 1}) assert 'headers' in r.json() interaction = b.current_cassette.interactions[0].json assert 'base64_string' in interaction['request']['body'] assert 'base64_string' in interaction['response']['body']
def test_contacts_can_update(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('contacts/update') contact = self.client.contacts.retrieve("16565245-1b65-464e-affa-58313192b54f") assert contact is not None contact.login_id = "*****@*****.**" contact.update() assert contact.login_id == "*****@*****.**" contact = self.client.contacts.retrieve("16565245-1b65-464e-affa-58313192b54f") assert contact is not None assert contact.login_id == "*****@*****.**"
def test_presence_batch(xbl_client): with Betamax(xbl_client.session).use_cassette('presence_batch'): ret = xbl_client.presence.get_presence_batch( ['2669321029139235', '2584878536129841']) assert ret.status_code == 200 data = ret.json() assert len(data) == 2 assert data[0]['xuid'] == '2669321029139235' assert data[0]['state'] == 'Offline' assert data[1]['xuid'] == '2584878536129841' assert data[1]['state'] == 'Offline'
def test_search_for_spotify_on_sv_blogs_using_query_object(self): c = twingly_search.Client() with Betamax(c._session).use_cassette( 'search_for_spotify_on_sv_blogs_using_query'): q = c.query() q.search_query = 'spotify page-size:20' q.language = 'en' q.start_time = dateutil.parser.parse("2017-03-09 18:03:43") result = c.execute_query(q) self.assertIsNotNone(result) self.assertEqual(result.incomplete_result, False) self.assertEqual(result.number_of_matches_returned, 1) self.assertEqual(len(result.posts), 1)
def test_correct_email_and_password(self): with Betamax(xbox.client.session) as vcr: match_on = ['uri', 'method', 'headers', 'body'] vcr.use_cassette( 'correct_password', match_on=match_on, record_mode='never', ) # the response was recorded with the correct credentials and edited assert not xbox.client.authenticated xbox.client.authenticate('*****@*****.**', 'password') assert xbox.client.authenticated assert xbox.client.AUTHORIZATION_HEADER == 'XBL3.0 x=1674471606081042789;eyJlbmMiOiJBMTI4Q0JDK0hTMjU2IiwiYWxnIjoiUlNBLU9BRVAiLCJjdHkiOiJKV1QiLCJ6aXAiOiJERUYiLCJ4NXQiOiIxZlVBejExYmtpWklFaE5KSVZnSDFTdTVzX2cifQ.W-xZJv-Cm0JrzJ2hHwPBnaFbusjcs2W16qb9aIZJmSqgU7NAElZ_WNQxMOgqn81OpyU41Bj9_DQUqT-QLDoluYT4xQvw44TX0-NGh3-gfy9RmZbf1mh_h3gv8oQRbPk5hxuwU9MmA2CrkLt0-yHoosgWOQtUbs9J0LvRoUtIigY.luE3Rdn7hxl1c1wLryVUDQ.OtZOM2ADr7FfjdM21C5-D_Bb45gPjoHP44J3OdpwvAG101QndHxhGIQSJ_akDHh6DNowf0Gn1xN_K6688aKA0n50uwxYq2S1um-gLRH_EgwY8yHwFQHhN0ZTb571TaLyIOj5riK9o-mHYxf8al3ZGkORzptoP7Y1WCifmTggOR8qvrCUeBawHCvCIem8rz72aTU4TMVHYXuKlek1ANiv816XCtCrNwnyil9DJzGZcjhChojgV6qpSkVknyAy_O996CmMa3P4S2cSSzN59LWgDNqSx0J9YlagVTB2croqbmyqtsffj5Gt81CY1kbOynzuM6mcCUuTFCMn6HgkdImQQbolJnxteN7tJQBkKx0PX8OYnK09p0GpFWn6UtO-a5BRkKRuBO5lQnAtOdHL4pYM9cPAxLz1rzjT13Fm9tFpxZpwAPQAPk9runNPKYns1loip2IU41yQ_-BRbByhZ0VVnvu8aV3vHJJdt7R8ePEpRnt5IL2UQNedfYQrI-L3WzMPoMkEcuunUrhie9RNRlXEaBL-TxmMcIJ7qIeteUT0EHYGlWm9lmAjJ9FBSgUOW87MPslpgAM-Th4-6_iMREmG2TsG2v2mT6EYRZQsbsT3rZXijwmV2Ts_UIBlB2GmaIua0uXivesG0xad5HWQAtTzvhxjFnkaVXlcaNXFnYOmJz00ktUUdmExL_s0qvhVhYNN77jhc7S4TYDoU-FxZZDeT23B9j8o758Giv5pTcKuz9aFK5iRXQMPnfHY4miJWq2MMWf1zpfh4vandrRTn3HxBV-q1MGrX2dAjGcIpCZ5hOfaT75tZEl_xJe-boV0bqwI2t-4cYw1AgLIYDR0b4YIrZUjUnEzH_6gZU0IaoFvw8-dm2F3x2crC7iK_EWPNdpyr-tDYxLXOZWz0MA4tlixrGZuywYGR09C-tHSIWanztI0O5536S7wDLFeCQUgBp4yUmsgfeP9sP6obUIS-a1E8e0glUzJAD4b08aypbrOgrCW08GLJjrgG1H2GYNxVGanHJiHRPnUQ3fIFsT2aBza1RMQQwUilZKxg_R3AhJdoBL_H20hAaJ2BiSPl_2QBfYUgqw-iDP-k5iKCakc6LXvexF2ZnPOdBVyG_Rg8Aj0cwus8Nur2LOxUxbArRe8TuAqPYh9hpEbuSvqsMImYqL9uLMtR4LiC9nc8ihG0uzepml0ozeiGCdFw9sLxIm-cokdTYxgC5uO-bOYhzjqu5TGiw.ommE112Hsa9zaNkQIz4sztyVUSqRl-3zh8NO-e5Mwa8'
def test_request__post(self): with Betamax(REQUESTOR).use_cassette('Session_request__post'): session = prawcore.Session(script_authorizer()) data = { 'kind': 'self', 'sr': 'reddit_api_test', 'text': 'Test!', 'title': 'A Test from PRAWCORE.' } key_count = len(data) response = session.request('POST', '/api/submit', data=data) self.assertIn('a_test_from_prawcore', response['json']['data']['url']) self.assertEqual(key_count, len(data)) # Ensure data is untouched
def test_reference_can_retrieve_settlement_accounts(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('reference/can_retrieve_settlement_accounts') settlement_accounts = self.client.reference.settlement_accounts( currency='GBP') assert len(settlement_accounts) > 0 settlement_account = settlement_accounts[0] assert isinstance(settlement_account, SettlementAccount) assert settlement_account.bank_name assert 'The Currency Cloud GBP' in settlement_account.bank_account_holder_name # noqa
def test_transfers_can_create(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('transfers/can_create') transfer = self.client.transfers.create( source_account_id="d0ad035e-b699-4fcd-a73c-13fb0910a884", destination_account_id="e54a5e86-80ad-4434-90fe-0c8c751666de", currency="GBP", amount="1000") assert transfer is not None assert isinstance(transfer, Transfer) assert transfer.currency == "GBP"
def test_reference_can_retrieve_settlement_accounts(self): session = currencycloud.session(authenticate=False) with Betamax(session.requests_session) as betamax: betamax.use_cassette('reference/can_retrieve_settlement_accounts') settlement_accounts = Reference.settlement_accounts(currency='GBP') assert len(settlement_accounts) > 0 settlement_account = settlement_accounts[0] assert isinstance(settlement_account, SettlementAccount) assert settlement_account.bank_name assert 'The Currency Cloud GBP' in settlement_account.bank_account_holder_name # noqa
def test_transactions_can_find(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('transactions/can_find') transactions = self.client.transactions.find(currency="GBP", per_page=1) assert len(transactions) == 1 transaction = transactions[0] assert transaction is not None assert isinstance(transaction, Transaction) assert transaction.currency == "GBP"
def testMockSPARQLError(self): """Test a SPARQL query against a mocked-up endpoint.""" test_query = """PREFIX dc: <http://purl.org/dc/terms/> SELECT ?product ?title WHERE { ?product dc:title ?title } LIMIT 10""" sparql = SPARQLServer( 'http://localhost/tenuki/sparql', post_queries=True, ) with Betamax(sparql.s).use_cassette( 'mock_sparql_error', record='none', ): self.assertRaises(SPARQLQueryException, sparql.query, test_query)
def test_request__conflict(self): with Betamax(REQUESTOR).use_cassette('Session_request__conflict'): session = prawcore.Session(script_authorizer()) previous = 'f0214574-430d-11e7-84ca-1201093304fa' with self.assertRaises(prawcore.Conflict) as context_manager: session.request('POST', '/r/ThirdRealm/api/wiki/edit', data={ 'content': 'New text', 'page': 'index', 'previous': previous }) self.assertEqual(409, context_manager.exception.response.status_code)
def test_refresh(self): authorizer = prawcore.ScriptAuthorizer( self.authentication, USERNAME, PASSWORD ) self.assertIsNone(authorizer.access_token) self.assertIsNone(authorizer.scopes) self.assertFalse(authorizer.is_valid()) with Betamax(REQUESTOR).use_cassette("ScriptAuthorizer_refresh"): authorizer.refresh() self.assertIsNotNone(authorizer.access_token) self.assertEqual(set(["*"]), authorizer.scopes) self.assertTrue(authorizer.is_valid())
def test_request__post__with_files(self): with Betamax(REQUESTOR).use_cassette( 'Session_request__post__with_files', match_requests_on=['uri', 'method']): session = prawcore.Session(script_authorizer()) data = {'upload_type': 'header'} with open('tests/files/white-square.png', 'rb') as fp: files = {'file': fp} response = session.request( 'POST', '/r/reddit_api_test/api/upload_sr_img', data=data, files=files) self.assertIn('img_src', response)
def test_reference_can_retrieve_currencies(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('reference/can_retrieve_currencies') currencies = self.client.reference.currencies() assert len(currencies) > 0 currency = currencies[0] assert isinstance(currency, Currency) assert currency.code == 'AED' assert currency.name == 'United Arab Emirates Dirham' assert currency.decimal_places == 2
def test_margin_balances_top_up(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('balances/top_up_margin') top_up = self.client.balances.top_up_margin(currency="GBP", amount="450") assert top_up assert top_up["currency"] == "GBP" assert top_up["transferred_amount"] == "450.0" assert top_up[ "account_id"] == "6c046c51-2387-4004-8e87-4bf97102e36d" assert isinstance(top_up, MarginBalanceTopUp)
def tl_searcher(request): tl_searcher = Tracker() session = tl_searcher.session betamax = Betamax(session, cassette_library_dir=config.cassette_library_dir) betamax.use_cassette(request.function.__name__) betamax.start() request.addfinalizer(betamax.stop) return tl_searcher
def test_reference_can_retrieve_payment_fee_rules(self): with Betamax(self.client.config.session) as betamax: betamax.use_cassette('reference/can_retrieve_payment_fee_rules') payment_fee_rules1 = self.client.reference.payment_fee_rules() assert len(payment_fee_rules1) == 3 fee_rule1_1 = payment_fee_rules1[0] assert isinstance(fee_rule1_1, PaymentFeeRule) assert fee_rule1_1.charge_type == "shared" assert fee_rule1_1.fee_amount == "2.00" assert fee_rule1_1.fee_currency == "AED" assert fee_rule1_1.payment_type == "priority" fee_rule1_2 = payment_fee_rules1[1] assert isinstance(fee_rule1_2, PaymentFeeRule) assert fee_rule1_2.charge_type == "shared" assert fee_rule1_2.fee_amount == "12.00" assert fee_rule1_2.fee_currency == "USD" assert fee_rule1_2.payment_type == "regular" fee_rule1_3 = payment_fee_rules1[2] assert isinstance(fee_rule1_3, PaymentFeeRule) assert fee_rule1_3.charge_type == "ours" assert fee_rule1_3.fee_amount == "5.25" assert fee_rule1_3.fee_currency == "GBP" assert fee_rule1_3.payment_type == "priority" payment_fee_rules2 = self.client.reference.payment_fee_rules( payment_type='regular') assert len(payment_fee_rules2) == 1 fee_rule2_1 = payment_fee_rules2[0] assert isinstance(fee_rule2_1, PaymentFeeRule) assert fee_rule2_1.charge_type == "shared" assert fee_rule2_1.fee_amount == "12.00" assert fee_rule2_1.fee_currency == "USD" assert fee_rule2_1.payment_type == "regular" payment_fee_rules3 = self.client.reference.payment_fee_rules( charge_type='ours') assert len(payment_fee_rules3) == 1 fee_rule3_1 = payment_fee_rules3[0] assert isinstance(fee_rule3_1, PaymentFeeRule) assert fee_rule3_1.charge_type == "ours" assert fee_rule3_1.fee_amount == "5.25" assert fee_rule3_1.fee_currency == "GBP" assert fee_rule3_1.payment_type == "priority"
def test_customer_modify_doesnt_wipe_additional_data(api, name, gender, address, phone, email): additional_data = { 'birth_date': date(1980, 5, 10), } placeholders = list( _to_placeholders(name=name, gender=gender, address=address, phone=phone, email=email)) with Betamax(api.session) as recorder: with recorder.use_cassette('test_customer_modify_doesnt_wipe_1', placeholders=placeholders): handle = api.customer.create_customer( name, gender, address, phone, email, additional_data=additional_data) assert isinstance(handle, str) placeholders.append(_to_placeholder('handle', handle)) with recorder.use_cassette('test_customer_modify_doesnt_wipe_2', placeholders=placeholders): customer = api.customer.retrieve_customer( handle, with_additional_data=True) assert customer.additional_data.birth_date == '1980-05-10' result = api.customer.modify_customer(handle, address, phone, email) assert result is True with recorder.use_cassette('test_customer_modify_doesnt_wipe_3', placeholders=placeholders): customer = api.customer.retrieve_customer( handle, with_additional_data=True) assert customer.additional_data.birth_date == '1980-05-10' result = api.customer.delete_customer(handle) assert result is True with recorder.use_cassette('test_customer_modify_doesnt_wipe_4', placeholders=placeholders): with pytest.raises(NoSuchElement): api.customer.retrieve_customer(handle)
def test_reference_can_retrieve_currencies(self): session = currencycloud.session(authenticate=False) with Betamax(session.requests_session) as betamax: betamax.use_cassette('reference/can_retrieve_currencies') currencies = Reference.currencies() assert len(currencies) > 0 currency = currencies[0] assert isinstance(currency, Currency) assert currency.code == 'AED' assert currency.name == 'United Arab Emirates Dirham' assert currency.decimal_places == 2
def test_profile_by_xuid(xbl_client): with Betamax(xbl_client.session).use_cassette('usersearch_live_search'): ret = xbl_client.usersearch.get_live_search('tux') assert ret.status_code == 200 data = ret.json() assert len(data['results']) == 8 result = data['results'][0] assert result['text'] == 'Tux' assert result['result']['id'] == '2533274895244106' assert result['result']['score'] == 0.0 assert result['result']['gamertag'] == 'Tux' assert result['result']['displayPicUri'].startswith('http://images-eds.xboxlive.com/image?url=')
def setUpClass(cls): cls.session = Session() cls.recorder = Betamax(cls.session, default_cassette_options={'serialize_with': 'prettyjson'}) cls.gc = Geocaching(session=cls.session) try: cls.gc.login(username, password) except Error: # LoginFailedException is raised with invalid creds; Error is raised # with no network connection. This is okay as long as we aren't # recording new cassettes. If we are recording new cassettes, they # will indeed fail. But we shouldn't record and replay setup login, # because if we are recording new cassettes this means we cannot get # properly logged in. cls.gc._logged_in = True # we're gonna trick it cls.gc._session = cls.session # it got redefined; fix it
def test_request__unsupported_media_type(self): with Betamax(REQUESTOR).use_cassette( "Session_request__unsupported_media_type" ): session = prawcore.Session(script_authorizer()) exception_class = prawcore.SpecialError data = { "content": "type: submission\naction: upvote", "page": "config/automoderator", } with self.assertRaises(exception_class) as context_manager: session.request("POST", "r/ttft/api/wiki/edit/", data=data) self.assertEqual( 415, context_manager.exception.response.status_code )
def configure_betamax(api, **additional_apis): with Betamax.configure() as config: config.cassette_library_dir = 'tests/fixtures/cassettes' config.match_requests_on = ['method', 'uri', 'body'] def _set_api(api, template): for attr in ('username', 'password', 'password_hash'): value = getattr(api, attr, None) if value: config.define_cassette_placeholder(template % attr.upper(), value) # Configure primary API config.define_cassette_placeholder('<URL>', api.url) _set_api(api, '<%s>') # Any additional APIs for name, api in additional_apis.items(): template = '<' + name.upper() + '_%s>' if name else '<%s>' _set_api(api, template)
def configure_betamax(api, **additional_apis): with Betamax.configure() as config: config.cassette_library_dir = 'tests/fixtures/cassettes' config.default_cassette_options['match_options'] = ['method', 'uri', 'body'] def _set_api(api, template): for attr in ('username', 'password', 'password_hash'): value = getattr(api, attr, None) if value: config.define_cassette_placeholder(template % attr.upper(), value) # Configure primary API config.define_cassette_placeholder('<URL>', api.url) _set_api(api, '<%s>') # placeholders aren't replaced in gzipped responses api.session.headers['Accept-Encoding'] = '' # Any additional APIs for name, api in additional_apis.items(): template = '<' + name.upper() + '_%s>' if name else '<%s>' _set_api(api, template) # placeholders aren't replaced in gzipped responses api.session.headers['Accept-Encoding'] = ''
class SalesforceRestMatcher(BaseMatcher): name = "salesforce_rest" excluded_query_keys = ("start", "end") def to_dict(self, query): query_dict = parse_qs(query or "") # Protect against None return dict(filter(lambda i: i[0] not in self.excluded_query_keys, query_dict.items())) def match(self, request, recorded_request): request_query = self.to_dict(urlparse(request.url).query) recorded_query = self.to_dict(urlparse(recorded_request["uri"]).query) return request_query == recorded_query Betamax.register_request_matcher(SalesforceRestMatcher) custom_object_name = primitives.capital_word(charset=string.lowercase) with Betamax.configure() as config: config.define_cassette_placeholder("__CUSTOM_OBJECT_NAME__", custom_object_name) #### Fixtures #### @pytest.yield_fixture(scope="module") def metadata_client(request): Client = getattr(request.module, "metadata_client_class") client = Client(client_id, client_secret, domain, access_token) cassette_name = ".".join((request.module.__name__, "metadata"))
from urllib.parse import quote_plus from betamax import Betamax from betamax_serializers.pretty_json import PrettyJSONSerializer from requests import Session from pycaching.errors import Error from pycaching.geocaching import Geocaching from .helpers import sanitize_cookies username = os.environ.get('PYCACHING_TEST_USERNAME') or 'USERNAMEPLACEHOLDER' password = os.environ.get('PYCACHING_TEST_PASSWORD') or 'PASSWORDPLACEHOLDER' path = str(Path('test/cassettes')) with Betamax.configure() as config: config.cassette_library_dir = path config.define_cassette_placeholder('<USERNAME>', quote_plus(username)) config.define_cassette_placeholder('<PASSWORD>', quote_plus(password)) config.before_record(callback=sanitize_cookies) Betamax.register_serializer(PrettyJSONSerializer) class NetworkedTest(unittest.TestCase): """Class to represent tests that perform network requests""" @classmethod def setUpClass(cls): cls.session = Session() cls.recorder = Betamax(cls.session, default_cassette_options={'serialize_with': 'prettyjson'})
class TestSubmit(): def setup(self): self.session = Session() self.betamax = Betamax(self.session) self.cs = ContentService(url=URL, apikey=APIKEY, session=self.session) assert_true(CONFIG.is_valid()) def test_submit_assets(self): with self.betamax.use_cassette('test_submit_assets'): result = submit_assets('test/fixtures/assets', 10000, self.cs) assert_equal(result.uploaded, 2) assert_equal(result.present, 0) aaa, bbb = None, None for asset in result.asset_set.all(): if asset.localpath == 'foo/aaa.jpg': aaa = asset elif asset.localpath == 'bar/bbb.gif': bbb = asset else: assert_true(False, 'Unrecognized asset: {}'.format(asset.localpath)) assert_is_not_none(aaa) assert_is_not_none(bbb) assert_equal(aaa.public_url, '/__local_asset__/aaa-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.jpg') assert_equal(bbb.public_url, '/__local_asset__/bbb-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.gif') def test_submit_assets_batches(self): with self.betamax.use_cassette('test_submit_assets_batches'): result = submit_assets('test/fixtures/batched_assets', 25000, self.cs) assert_equal(result.uploaded, 4) assert_equal(result.batches, 2) assert_equal(result.present, 0) def test_submit_envelopes(self): with self.betamax.use_cassette('test_submit_envelopes'): asset_set = AssetSet() asset_set.append(Asset('foo/aaa.jpg', io.BytesIO())) asset_set.append(Asset('bar/bbb.gif', io.BytesIO())) asset_set.accept_urls({ 'foo/aaa.jpg': '/__local_asset__/aaa-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.jpg', 'bar/bbb.gif': '/__local_asset__/bbb-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.gif' }) result = submit_envelopes( 'test/fixtures/envelopes', asset_set, 'https://github.com/org/repo/', self.cs ) assert_equal(result.uploaded, 3) assert_equal(result.present, 0) assert_equal(result.failed, 0) one, two, three = None, None, None for envelope in result.envelope_set.all(): if envelope.content_id() == 'https://github.com/org/repo/one': one = envelope elif envelope.content_id() == 'https://github.com/org/repo/two': two = envelope elif envelope.content_id() == 'https://github.com/org/repo/three': three = envelope else: assert_true(False, 'Unrecognized envelope: {}'.format(envelope.content_id())) assert_is_not_none(one) assert_is_not_none(two) assert_is_not_none(three) def test_submit_success(self): # Record this one with an empty content service. with self.betamax.use_cassette('test_submit_success'): result = submit(CONFIG, self.session) assert_equal(result.asset_result.uploaded, 2) assert_equal(result.asset_result.present, 0) assert_equal(result.envelope_result.uploaded, 3) assert_equal(result.envelope_result.present, 0) assert_equal(result.envelope_result.deleted, 0) assert_equal(result.envelope_result.failed, 0) assert_equal(result.state, SUCCESS) def test_submit_noop(self): # Record this one with an empty content service. with self.betamax.use_cassette('test_submit_noop'): result = submit(CONFIG, self.session) assert_equal(result.asset_result.uploaded, 0) assert_equal(result.asset_result.present, 2) assert_equal(result.envelope_result.uploaded, 0) assert_equal(result.envelope_result.present, 3) assert_equal(result.envelope_result.deleted, 0) assert_equal(result.envelope_result.failed, 0) assert_equal(result.state, NOOP)
def setUp(self): super(TestPlaceholders, self).setUp() config = Betamax.configure() config.define_cassette_placeholder('<AUTHORIZATION>', b64_foobar)
def setup(self): self.session = Session() self.betamax = Betamax(self.session) self.cs = ContentService(url=URL, apikey=APIKEY, session=self.session) assert_true(CONFIG.is_valid())
from besnappy.tickets import SnappyApiSender CASSETTE_LIBRARY_DIR = os.path.join(os.path.dirname(__file__), "cassettes") BESNAPPY_TEST_API_KEY = os.environ.get("BESNAPPY_TEST_API_KEY") class PrettyJSONSerializer(JSONSerializer): name = 'prettyjson' def serialize(self, cassette_data): return json.dumps( cassette_data, sort_keys=True, indent=2, separators=(',', ': ')) Betamax.register_serializer(PrettyJSONSerializer) class _AuthHeaderGrabberFakeRequest(object): def __init__(self): self.headers = {} @property def auth_header_value(self): return self.headers.get("Authorization") def basic_auth_header_value(api_key): r = _AuthHeaderGrabberFakeRequest() HTTPBasicAuth(api_key, "x")(r) return r.auth_header_value
class TestContentService(): def setup(self): session = Session() self.betamax = Betamax(session) self.cs = ContentService(url=URL, apikey=APIKEY, session=session) def test_checkassets(self): # curl -X POST -H "Authorization: deconst ${APIKEY}" \ # http://dockerdev:9000/assets \ # -F aaa=@test/fixtures/assets/foo/aaa.jpg \ # -F bbb=@test/fixtures/assets/bar/bbb.gif with self.betamax.use_cassette('checkassets'): response = self.cs.checkassets({ 'foo/aaa.jpg': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'bar/bbb.gif': '8810ad581e59f2bc3928b261707a71308f7e139eb04820366dc4d5c18d980225', 'baz/missing.css': 'ffa63583dfa6706b87d284b86b0d693a161e4840aad2c5cf6b5d27c3b9621f7d' }) assert_equal(response, { 'foo/aaa.jpg': '/__local_asset__/aaa-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.jpg', 'bar/bbb.gif': None, 'baz/missing.css': None }) def test_bulkasset(self): with self.betamax.use_cassette('bulkasset'): tarball = io.BytesIO() tf = tarfile.open(fileobj=tarball, mode='w:gz') add_tar_entry(tf, 'bar/bbb.gif') add_tar_entry(tf, 'foo/aaa.jpg') tf.close() response = self.cs.bulkasset(tarball.getvalue()) assert_equal(response, { 'bar/bbb.gif': '/__local_asset__/bbb-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.gif', 'foo/aaa.jpg': '/__local_asset__/aaa-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.jpg' }) def test_checkcontent(self): # curl -X PUT -H "Authorization: deconst ${APIKEY}" \ # -H 'Content-Type: application/json' \ # http://dockerdev:9000/content/https%3A%2F%2Fgithub.com%2Forg%2Frepo%2Fone \ # -d '{"title":"one","body":"one"}' # echo -n '{"body":"one","title":"one"}' | shasum -a 256 # curl -X PUT -H "Authorization: deconst ${APIKEY}" \ # -H 'Content-Type: application/json' \ # http://dockerdev:9000/content/https%3A%2F%2Fgithub.com%2Forg%2Frepo%2Ftwo \ # -d '{"title":"two","body":"two"}' # echo -n '{"body":"two","title":"two"}' | shasum -a 256 with self.betamax.use_cassette('checkcontent'): response = self.cs.checkcontent({ 'https://github.com/org/repo/one': '842d36ad29589a39fc4be06157c5c204a360f98981fc905c0b2a114662172bd8', 'https://github.com/org/repo/two': 'f0e62392fc00c71ba3118c91b97c6f2cbfdcd75e8053fe2d9f029ebfcf6c23fe' }) assert_equal(response, { 'https://github.com/org/repo/one': True, 'https://github.com/org/repo/two': False }) def test_bulkcontent(self): with self.betamax.use_cassette('bulkcontent'): tarball = io.BytesIO() tf = tarfile.open(fileobj=tarball, mode='w:gz') add_tar_entry( tf, 'https%3A%2F%2Fgithub.com%2Forg%2Frepo%2Fone.json', b'{"body":"one","title":"one"}') add_tar_entry( tf, 'https%3A%2F%2Fgithub.com%2Forg%2Frepo%2Ftwo.json', b'{"body":"two","title":"two"}') tf.close() response = self.cs.bulkcontent(tarball.getvalue()) assert_equal(response, { 'accepted': 2, 'failed': 0, 'deleted': 0 })
from betamax import Betamax from requests import Session from unittest import TestCase, main from zohocrm import api with Betamax.configure() as config: config.cassette_library_dir = 'cassettes' class ZohoAPITestCase(TestCase): def setUp(self): self.session = Session() self.invalid_api = api.API(auth_token='INVALID_TOKEN') self.api = api.API(auth_token='597a7029c4ea163c7a3ffeed2816c7a2', session=self.session) self.record = { 'Lead Source': 'Web Download', 'Company': 'Your Company', 'First Name': 'Hannah', 'Last Name': 'Smith', 'Email': '*****@*****.**', 'Title': 'Manager', 'Phone': '1234567890', 'Home Phone': '0987654321', } self.control = '''<Leads> <row no="1"> <FL val="First Name"><![CDATA[Hannah]]></FL> <FL val="Title"><![CDATA[Manager]]></FL> <FL val="Last Name"><![CDATA[Smith]]></FL>
class TestSnappyApiSender(TestCase): def setUp(self): self.api_key = "dummy_key" self.betamax_record = "none" if os.environ.get("BESNAPPY_TEST_RECORD_REQUESTS"): if BESNAPPY_TEST_API_KEY: self.betamax_record = "all" self.api_key = BESNAPPY_TEST_API_KEY else: raise RuntimeError( "BESNAPPY_TEST_RECORD_REQUESTS is set, but" " BESNAPPY_TEST_API_KEY is not.") self.no_http_session = TestSession() self.betamax_session = Session() # We reset the Accept-Encoding header to avoid storing (opaque) gzip # response data. self.betamax_session.headers["Accept-Encoding"] = "" self.betamax = Betamax( self.betamax_session, cassette_library_dir=CASSETTE_LIBRARY_DIR) self.common_session = Session() # We reset the Accept-Encoding header to avoid storing (opaque) gzip # response data. self.common_session.headers["Accept-Encoding"] = "" self.betamax_common = Betamax( self.common_session, cassette_library_dir=CASSETTE_LIBRARY_DIR) self.betamax_placeholders = [] self.common_snappy = self._get_common_snappy() def tearDown(self): self.betamax.stop() self.betamax_common.stop() def add_betamax_placeholder(self, placeholder, replace): placeholder_dict = {"placeholder": placeholder, "replace": replace} if placeholder_dict not in self.betamax_placeholders: self.betamax_placeholders.append(placeholder_dict) def snappy_for_session(self, session, api_key=None, api_url=None): """ Build a ``SnappyApiSender`` instance using the provided session. """ if api_key is None: api_key = self.api_key return SnappyApiSender(api_key, api_url=api_url, session=session) def _snappy_for_betamax(self, betamax, cassette_name, api_key, api_url): """ Build a ``SnappyApiSender`` instance using the provided betamax object. """ if api_key is None: api_key = self.api_key auth_header_value = basic_auth_header_value(api_key) self.add_betamax_placeholder("$AUTH_HEADER$", auth_header_value) betamax.use_cassette( cassette_name, record=self.betamax_record, serialize_with="prettyjson", placeholders=self.betamax_placeholders, match_requests_on=["method", "uri"]) betamax.start() return self.snappy_for_session(betamax.session, api_key, api_url) def get_snappy(self, api_key=None, api_url=None): """ Build a ``SnappyApiSender`` instance using the test session. """ return self._snappy_for_betamax( self.betamax, self.id(), api_key, api_url) def _get_common_snappy(self, api_key=None, api_url=None): """ Build a ``SnappyApiSender`` instance using the common session. This uses a shared betamax cassette and is suitable for requests that set up the environment for the test to use rather than being part of the test logic. """ return self._snappy_for_betamax( self.betamax_common, "common", api_key, api_url) def test_api_request_url_construction_default_api_url(self): """ ``._api_request()`` constructs a URL by appending the ``endpoint`` to the ``api_url``. In this case, we use the default API URL. """ snappy = self.snappy_for_session(self.no_http_session) self.no_http_session.mount( "%s/flash" % (snappy.api_url,), TestAdapter("ok")) resp = snappy._api_request("GET", "flash") self.assertEqual(resp.content, "ok") def test_api_request_url_construction_custom_api_url(self): """ ``._api_request()`` constructs a URL by appending the ``endpoint`` to the ``api_url``. In this case, we provide a custom API URL. """ snappy = self.snappy_for_session( self.no_http_session, api_url="http://snappyapi.example.com/v1") self.no_http_session.mount( "http://snappyapi.example.com/v1/flash", TestAdapter("ok")) resp = snappy._api_request("GET", "flash") self.assertEqual(resp.content, "ok") #################################### # Tests for public API below here. # #################################### def get_account_id(self): """ Get an account_id for use in further tests. This uses the common betamax instead of the test-specific one. Because we don't have very much control over the account we're testing against, we always choose the first account in the list. """ accounts = self.common_snappy.get_accounts() return accounts[0]["id"] def get_mailbox_id(self): """ Get a mailbox_id for use in further tests. This uses the common betamax instead of the test-specific one. Because we don't have very much control over the account we're testing against, we always choose the first mailbox in first account in the list. """ account_id = self.get_account_id() mailboxes = self.common_snappy.get_mailboxes(account_id) return mailboxes[0]["id"] def get_staff_id(self): """ Get a staff_id for use in further tests. This uses the common betamax instead of the test-specific one. Because we don't have very much control over the account we're testing against, we always choose the first staff entry in first account in the list. """ account_id = self.get_account_id() staff = self.common_snappy.get_staff(account_id) return staff[0]["id"] def assert_looks_like_account_dict(self, obj): """ Assertion fails if the provided object doesn't look sufficiently like an account dict. TODO: Determine if this is good enough. """ self.assertTrue(isinstance(obj, dict), "Not a dict: %r" % (obj,)) account_fields = set([ "id", "organization", "domain", "plan_id", "active", "created_at", "updated_at", "custom_domain"]) missing_fields = account_fields - set(obj.keys()) self.assertEqual( missing_fields, set(), "Dict missing account fields: %s" % ( ", ".join(sorted(missing_fields)),)) def assert_looks_like_mailbox_dict(self, obj, account_id): """ Assertion fails if the provided object doesn't look sufficiently like a mailbox dict belonging to the specified account. TODO: Determine if this is good enough. """ self.assertTrue(isinstance(obj, dict), "Not a dict: %r" % (obj,)) mailbox_fields = set([ "id", "account_id", "type", "address", "display", "auto_responding", "auto_response", "active", "created_at", "updated_at", "custom_address", "theme", "local_part"]) missing_fields = mailbox_fields - set(obj.keys()) self.assertEqual( missing_fields, set(), "Dict missing mailbox fields: %s" % ( ", ".join(sorted(missing_fields)),)) self.assertEqual(obj["account_id"], account_id) def assert_looks_like_staff_dict(self, obj): """ Assertion fails if the provided object doesn't look sufficiently like a staff dict. TODO: Determine if this is good enough. """ self.assertTrue(isinstance(obj, dict), "Not a dict: %r" % (obj,)) staff_fields = set([ "id", "email", "sms_number", "first_name", "last_name", "photo", "culture", "notify", "created_at", "updated_at", "signature", "tour_played", "timezone", "notify_new", "news_read_at", "username"]) missing_fields = staff_fields - set(obj.keys()) self.assertEqual( missing_fields, set(), "Dict missing staff fields: %s" % ( ", ".join(sorted(missing_fields)),)) def test_get_accounts(self): """ ``.get_accounts()`` returns a list of accounts. Because we don't have very much control over the account we're testing against, we can only assert on the general structure. We always choose the first account in the list. """ snappy = self.get_snappy() accounts = snappy.get_accounts() self.assertTrue(isinstance(accounts, list)) self.assertTrue(len(accounts) >= 1) account = accounts[0] self.assert_looks_like_account_dict(account) # TODO: Make a call that requires an account identifier and assert that # it succeeds. def test_get_mailboxes(self): """ ``.get_mailboxes()`` returns a list of mailboxes for an account. Because we don't have very much control over the account we're testing against, we can only assert on the general structure. We always choose the first account in the list. """ account_id = self.get_account_id() snappy = self.get_snappy() mailboxes = snappy.get_mailboxes(account_id) self.assertTrue(isinstance(mailboxes, list)) self.assertTrue(len(mailboxes) >= 1) mailbox = mailboxes[0] self.assert_looks_like_mailbox_dict(mailbox, account_id) # TODO: Make a call that requires a mailbox identifier and assert that # it succeeds. def test_get_staff(self): """ ``.get_staff()`` returns a list of staffes for an account. Because we don't have very much control over the account we're testing against, we can only assert on the general structure. We always choose the first account in the list. """ account_id = self.get_account_id() snappy = self.get_snappy() staff = snappy.get_staff(account_id) self.assertTrue(isinstance(staff, list)) self.assertTrue(len(staff) >= 1) staff_member = staff[0] self.assert_looks_like_staff_dict(staff_member) # TODO: Make a call that requires a staff identifier and assert that # it succeeds. def test_create_note_new_ticket(self): """ Creating a note without a ticket identifier creates a new ticket. """ # NOTE: This placeholder needs to be set before we create the API # object betamax only loads its cassette data once upfront in # playback mode. subject_uuid = str(uuid.uuid4()) self.betamax_placeholders.append({ "placeholder": "$SUBJECT_UUID$", "replace": subject_uuid, }) mailbox_id = self.get_mailbox_id() snappy = self.get_snappy() ticket_subject = "Test subject %s" % (subject_uuid,) content = "What are the experiment protocols for subject %s?" % ( subject_uuid,) ticket_id = snappy.create_note( mailbox_id, ticket_subject, content, from_addr=[{ "name": "John Smith", "address": "*****@*****.**", }]) ticket_notes = snappy.get_ticket_notes(ticket_id) # A new ticket will only have one note. self.assertEqual( len(ticket_notes), 1, "Expected exactly 1 note, got %s: %r" % ( len(ticket_notes), ticket_notes)) [ticket_note] = ticket_notes # The note content should match the content we sent. self.assertEqual(strip_note_content(ticket_note["content"]), content) def test_create_note_new_private_from_staff(self): """ Creating a note without a ticket identifier creates a new ticket. """ # NOTE: This placeholder needs to be set before we create the API # object betamax only loads its cassette data once upfront in # playback mode. subject_uuid = str(uuid.uuid4()) self.betamax_placeholders.append({ "placeholder": "$SUBJECT_UUID$", "replace": subject_uuid, }) mailbox_id = self.get_mailbox_id() staff_id = self.get_staff_id() snappy = self.get_snappy() ticket_subject = "Private subject %s" % (subject_uuid,) content = "Has %s accepted the privacy policy?" % (subject_uuid,) addr = { "name": "John Smith", "address": "*****@*****.**", } ticket_id = snappy.create_note( mailbox_id, ticket_subject, content, to_addr=[addr], staff_id=staff_id, scope="private") ticket_notes = snappy.get_ticket_notes(ticket_id) # A new ticket will only have one note. self.assertEqual( len(ticket_notes), 1, "Expected exactly 1 note, got %s: %r" % ( len(ticket_notes), ticket_notes)) [ticket_note] = ticket_notes # The note content should match the content we sent. self.assertEqual(strip_note_content(ticket_note["content"]), content) def test_create_note_existing_ticket(self): """ Creating a note with a ticket identifier adds a note to the ticket. """ # NOTE: This placeholder needs to be set before we create the API # object betamax only loads its cassette data once upfront in # playback mode. subject_uuid = str(uuid.uuid4()) self.betamax_placeholders.append({ "placeholder": "$SUBJECT_UUID$", "replace": subject_uuid, }) mailbox_id = self.get_mailbox_id() snappy = self.get_snappy() # Create ticket ticket_subject = "Test subject %s" % (subject_uuid,) content = "What are the experiment protocols for subject %s?" % ( subject_uuid,) ticket_id = snappy.create_note( mailbox_id, ticket_subject, content, from_addr=[{ "name": "John Smith", "address": "*****@*****.**", }]) # Add a note to existing ticket. content_2 = "Do we need more goop for %s?" % (subject_uuid,) ticket_id_2 = snappy.create_note( mailbox_id, ticket_subject, content_2, ticket_id=ticket_id, from_addr=[{ "name": "John Smith", "address": "*****@*****.**", }]) # The ticket identifier should be the same. self.assertEqual(ticket_id, ticket_id_2) ticket_notes = snappy.get_ticket_notes(ticket_id) self.assertEqual( len(ticket_notes), 2, "Expected exactly 2 notes, got %s: %r" % ( len(ticket_notes), ticket_notes)) # NOTE: We have observed that the notes are ordered from newest to # oldest, but this is not documented. The note identifier appears # to be an increasing integer, but this is also not documented. # The timestamp lacks sufficient resolution to order the notes. # For now, we assume the observed ordering is consistent. [note_2, note_1] = ticket_notes # The note content should match the content we sent. self.assertEqual(strip_note_content(note_1["content"]), content) self.assertEqual(strip_note_content(note_2["content"]), content_2)
"""Return a base64 encoded string (not bytes) from input_string.""" return b64encode(input_string.encode("utf-8")).decode("utf-8") def env_default(key): """Return environment variable or placeholder string. Set environment variable to placeholder if it doesn't exist. """ test_environ = "prawtest_{}".format(key) test_value = os.environ.get(test_environ, "placeholder_{}".format(key)) return os.environ.setdefault("praw_{}".format(key), test_value) os.environ["praw_check_for_updates"] = "False" placeholders = {x: env_default(x) for x in "client_id client_secret password username".split()} placeholders["basic_auth"] = b64_string("{}:{}".format(placeholders["client_id"], placeholders["client_secret"])) Betamax.register_serializer(pretty_json.PrettyJSONSerializer) with Betamax.configure() as config: if os.getenv("TRAVIS"): config.default_cassette_options["record_mode"] = "none" config.cassette_library_dir = "tests/cassettes" config.default_cassette_options["serialize_with"] = "prettyjson" config.default_cassette_options["match_requests_on"].append("body") for key, value in placeholders.items(): config.define_cassette_placeholder("<{}>".format(key.upper()), value)
return urljoin(self.r.config.permalink_url, path) class OAuthPRAWTest(PRAWTest): def betamax_init(self): self.r.set_oauth_app_info(self.client_id, self.client_secret, self.redirect_uri) def setUp(self): self.configure() self.r = Reddit(USER_AGENT, site_name='reddit_oauth_test', disable_update_check=True) Betamax.register_request_matcher(BodyMatcher) Betamax.register_serializer(pretty_json.PrettyJSONSerializer) with Betamax.configure() as config: if os.getenv('TRAVIS'): config.default_cassette_options['record_mode'] = 'none' config.cassette_library_dir = 'tests/cassettes' config.default_cassette_options['match_requests_on'].append('PRAWBody') config.default_cassette_options['serialize_with'] = 'prettyjson' def betamax(cassette_name=None, **cassette_options): """Utilze betamax to record/replay any network activity of the test. The wrapped function's `betmax_init` method will be invoked if it exists.
def setup(self): session = Session() self.betamax = Betamax(session) self.cs = ContentService(url=URL, apikey=APIKEY, session=session)
unicode except NameError: basestring = unicode = str CREDS_FILENAME = os.getenv('GS_CREDS_FILENAME') SCOPE = [ 'https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive.file', ] DUMMY_ACCESS_TOKEN = '<ACCESS_TOKEN>' I18N_STR = u'Iñtërnâtiônàlizætiøn' # .encode('utf8') Betamax.register_serializer(JSONBodySerializer) def sanitize_token(interaction, current_cassette): headers = interaction.data['request']['headers'] token = headers.get('Authorization') if token is None: return interaction.data['request']['headers']['Authorization'] = [ 'Bearer %s' % DUMMY_ACCESS_TOKEN ] with Betamax.configure() as config:
class AwsBodyMatcher(BaseMatcher): name = 'aws-body' def match(self, request, recorded_request): recorded_request = deserialize_prepared_request(recorded_request) recorded_body = recorded_request.body.split('&') request_body = (request.body or b'').split('&') return sorted(request_body) == sorted(recorded_body) class Botomax(Betamax): def __init__(self, boto_resource, cassette_library_dir=None, default_cassette_options={}): try: session = boto_resource.meta.client._endpoint.http_session # if the boto resource is a low-level client we don't have # to do digg deeper into the object. except AttributeError: session = boto_resource._endpoint.http_session super(Botomax, self).__init__( session=session, cassette_library_dir=cassette_library_dir, default_cassette_options=default_cassette_options) Betamax.register_request_matcher(AwsBodyMatcher)
def tearDown(self): with Betamax.configure() as config: config.default_cassette_options['record_mode'] = 'once'
def setUp(self): with Betamax.configure() as config: config.default_cassette_options['record_mode'] = 'none'
first_hit = next((x for x in sequence if predicate(x)), None) self.assertTrue(first_hit) return first_hit def none(self, sequence, predicate): self.assertEqual( None, next((x for x in sequence if predicate(x)), None)) def setUp(self): self.configure() def url(self, path): return urljoin(self.r.config.permalink_url, path) Betamax.register_request_matcher(BodyMatcher) with Betamax.configure() as config: if os.getenv('TRAVIS'): config.default_cassette_options['record_mode'] = 'none' config.cassette_library_dir = 'tests/cassettes' config.default_cassette_options['match_requests_on'].append('PRAWBody') def betamax(cassette_name=None, **cassette_options): """Utilze betamax to record/replay any network activity of the test. The wrapped function's `betmax_init` method will be invoked if it exists. """ def factory(function): @wraps(function)
def setUp(self): self.session = Session() self.vcr = Betamax(self.session)