def test_mixpanel(httpserver: HTTPServer): httpserver.expect_request(re.compile('/(track|engage)')).respond_with_json({'status': 1}) options = MixpanelOptions( api_host=httpserver.url_for('').rstrip('/'), ) p = MixpanelPlugin('My-Key', options) assert p.id() == 'mixpanel' p.load(PluginLoadOptions(environment=Environment.DEVELOPMENT, logger=Logger.NONE)) p.identify("user-1", Properties(item1='value1', item2=2)) p.alias("user-1", "prev-user-1") p.track("user-2", Event('event-1', Properties(item1='value1', item2=1))) p.track("user-2", Event('event-2', Properties(item1='value2', item2=2))) p.flush() p.track("user-2", Event('event-3', Properties(item1='value3', item2=3))) p.track("user-2", Event('event-4', Properties(item1='value4', item2=4))) p.track("user-1", Event('event-5', Properties(item1='value5', item2=5))) p.shutdown() time.sleep(0.1) requests = _get_cleaned_requests(httpserver) httpserver.stop() assert requests == [ {'event': 'event-1', 'properties': {'distinct_id': 'user-2', 'item1': 'value1', 'item2': 1, 'mp_lib': 'python', 'token': 'My-Key'}}, {'event': 'event-2', 'properties': {'distinct_id': 'user-2', 'item1': 'value2', 'item2': 2, 'mp_lib': 'python', 'token': 'My-Key'}}, {'$distinct_id': 'user-1', '$set': {'item1': 'value1', 'item2': 2}, '$token': 'My-Key'}, {'event': 'event-3', 'properties': {'distinct_id': 'user-2', 'item1': 'value3', 'item2': 3, 'mp_lib': 'python', 'token': 'My-Key'}}, {'event': 'event-4', 'properties': {'distinct_id': 'user-2', 'item1': 'value4', 'item2': 4, 'mp_lib': 'python', 'token': 'My-Key'}}, {'event': 'event-5', 'properties': {'distinct_id': 'user-1', 'item1': 'value5', 'item2': 5, 'mp_lib': 'python', 'token': 'My-Key'}} ]
def test_events_disabled() -> None: user_id = 'test-user-id' itly = Itly() logger = CustomLogger() itly.load( context=Properties( requiredString='A required string', optionalEnum=OptionalEnum.Value1, ), options=Options( environment=Environment.PRODUCTION, plugins=[CustomPlugin()], logger=logger, disabled=True, ), ) itly.identify('user-id', Properties(user_prop=1)) itly.alias(user_id, 'user-id') itly.group(user_id, 'a-group-id', Properties(group_prop='test value')) itly.page(user_id, 'page category', 'page name', Properties(page_prop='a page property')) itly.track(user_id, Event('Event No Properties')) itly.track( user_id, Event( 'Event With All Properties', Properties( required_string='A required string', required_number=2.0, required_integer=42, required_enum=RequiredEnum.Enum1, required_boolean=False, required_const='some-const-value', required_array=['required', 'array'], optional_string="I'm optional!", ))) itly.flush() itly.track(user_id, Event('EventMaxIntForTest', Properties(int_max_10=20, ))) itly.flush() itly.shutdown() log_text = '\n'.join(logger.log_lines) assert log_text == '''[itly-core] disabled = True'''
def test_track_after_shutdown_throws_error() -> None: itly = Itly() itly.load() itly.shutdown() with pytest.raises(Exception) as ctx: itly.track('user-id', Event("event")) assert str(ctx.value) == 'Itly is shutdown. No more requests are possible.'
def test_track_before_load_throws_error() -> None: itly = Itly() with pytest.raises(Exception) as ctx: itly.track('user-id', Event("event")) assert str( ctx.value ) == 'Itly is not yet initialized. Have you called `itly.load()` on app start?'
def _check_validation_results( environment: Environment, validation_results: List[Tuple[ValidationOptions, Optional[str], str]] ) -> None: for validation_options, error_text, expected_log in validation_results: itly = Itly() logger = CustomLogger() itly.load( None, Options(environment=environment, logger=logger, plugins=[CustomPlugin()], validation=validation_options), ) if error_text is not None: with pytest.raises(Exception) as ctx: itly.track('user-id', Event("event", Properties(invalid=True))) assert str(ctx.value) == error_text else: itly.track('user-id', Event("event", Properties(invalid=True))) log_text = '\n'.join(logger.log_lines) assert expected_log == log_text
def test_TrackAndIdentify_ObjectAndArrayProperties_Stringified( httpserver: HTTPServer): httpserver.expect_request(re.compile('/users/track')).respond_with_data() p = BrazePlugin( 'My-Key', BrazeOptions(base_url=httpserver.url_for(''), flush_queue_size=100, flush_interval=timedelta_max)) p.load(plugin_load_options) p.identify("user-1", Properties(item1=[11, 'value2'], item2={ "a": True, "b": 17 })) p.track( "user-2", Event( 'event-1', Properties(item1=['value1', 'value2'], item2={ "a": 1, "b": "test" }))) p.flush() requests = _get_cleaned_requests(httpserver) assert requests == [ { 'attributes': [ { 'external_id': 'user-1', 'item1': '[11, "value2"]', 'item2': '{"a": true, "b": 17}' }, ], 'events': [ { 'external_id': 'user-2', 'name': 'event-1', 'properties': { 'item1': '["value1", "value2"]', 'item2': '{"a": 1, "b": "test"}' }, }, ], }, ] p.shutdown()
import json import re import time from datetime import timedelta from typing import List, Any from pytest_httpserver import HTTPServer from itly_plugin_braze import BrazePlugin, BrazeOptions from itly_sdk import PluginLoadOptions, Environment, Properties, Event, Logger time_short = 0.1 timedelta_max = timedelta(seconds=999) identify_properties = Properties(item1='identify', item2=2) event_1 = Event('event-1', Properties(item1='value1', item2=1)) event_2 = Event('event-2', Properties(item1='value2', item2=2)) plugin_load_options = PluginLoadOptions(environment=Environment.DEVELOPMENT, logger=Logger.NONE) def test_Id_BrazePlugin_IsBraze(): p = BrazePlugin('My-Key', BrazeOptions(base_url='')) assert p.id() == 'braze' def test_Identify_Immediate_Queued(httpserver: HTTPServer): httpserver.expect_request(re.compile('/users/track')).respond_with_data() p = BrazePlugin( 'My-Key', BrazeOptions(base_url=httpserver.url_for(''), flush_queue_size=100,
def test_amplitude_metadata(httpserver: HTTPServer): httpserver.expect_request( re.compile('/(events|identify)')).respond_with_data() options = AmplitudeOptions( events_endpoint=httpserver.url_for('/events'), identification_endpoint=httpserver.url_for('/identify'), metadata=AmplitudeMetadata(os_name='ubuntu', city="York", os_version="111.0")) p = AmplitudePlugin('My-Key', options) try: p.load( PluginLoadOptions(environment=Environment.DEVELOPMENT, logger=Logger.NONE)) p.identify("user-1", Properties(item1='value1', item2=2)) metadata = { "amplitude": AmplitudeMetadata(platform="LinUx", os_version="123.45") } p.track( "user-2", Event('event-1', Properties(item1='value1', item2=1), metadata=metadata)) metadata = { "amplitude": AmplitudeMetadata(os_name="win", os_version="987.45") } p.track( "user-1", Event('event-2', Properties(item1='value2', item2=2), metadata=metadata)) p.flush() time.sleep(0.1) requests = _get_cleaned_requests(httpserver) assert requests == [ [{ 'city': 'York', 'os_name': 'ubuntu', 'os_version': '111.0', 'user_id': 'user-1', 'user_properties': { 'item1': 'value1', 'item2': 2 } }], { 'api_key': 'My-Key', 'events': [{ 'user_id': 'user-2', 'event_type': 'event-1', 'event_properties': { 'item1': 'value1', 'item2': 1 }, 'city': 'York', 'platform': 'LinUx', 'os_name': 'ubuntu', 'os_version': "123.45" }, { 'user_id': 'user-1', 'event_type': 'event-2', 'event_properties': { 'item1': 'value2', 'item2': 2 }, 'city': 'York', 'os_name': 'win', 'os_version': "987.45" }], }, ] finally: p.shutdown() time.sleep(0.1) httpserver.stop()
def test_amplitude(httpserver: HTTPServer): httpserver.expect_request( re.compile('/(events|identify)')).respond_with_data() options = AmplitudeOptions( events_endpoint=httpserver.url_for('/events'), identification_endpoint=httpserver.url_for('/identify'), flush_queue_size=3, flush_interval=timedelta(seconds=1), ) p = AmplitudePlugin('My-Key', options) assert p.id() == 'amplitude' try: p.load( PluginLoadOptions(environment=Environment.DEVELOPMENT, logger=Logger.NONE)) p.identify("user-1", Properties(item1='value1', item2=2)) time.sleep(0.1) requests = _get_cleaned_requests(httpserver) assert requests == [] p.track("user-2", Event('event-1', Properties(item1='value1', item2=1))) time.sleep(0.1) requests = _get_cleaned_requests(httpserver) assert requests == [ [{ "user_id": "user-1", "user_properties": { "item1": "value1", "item2": 2 } }], ] p.track("user-2", Event('event-2', Properties(item1='value2', item2=2))) time.sleep(0.1) requests = _get_cleaned_requests(httpserver) assert requests == [ [{ "user_id": "user-1", "user_properties": { "item1": "value1", "item2": 2 } }], ] p.flush() time.sleep(0.1) requests = _get_cleaned_requests(httpserver) assert requests == [ [ { "user_id": "user-1", "user_properties": { "item1": "value1", "item2": 2 } }, ], { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-1', 'event_properties': { 'item1': 'value1', 'item2': 1 } }, { 'user_id': 'user-2', 'event_type': 'event-2', 'event_properties': { 'item1': 'value2', 'item2': 2 } }], 'api_key': 'My-Key' }, ] p.flush() p.flush() time.sleep(0.1) requests = _get_cleaned_requests(httpserver) assert requests == [ [{ "user_id": "user-1", "user_properties": { "item1": "value1", "item2": 2 } }], { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-1', 'event_properties': { 'item1': 'value1', 'item2': 1 } }, { 'user_id': 'user-2', 'event_type': 'event-2', 'event_properties': { 'item1': 'value2', 'item2': 2 } }], 'api_key': 'My-Key' }, ] p.track("user-2", Event('event-3', Properties(item1='value3', item2=3))) time.sleep(1.1) requests = _get_cleaned_requests(httpserver) assert requests == [ [{ "user_id": "user-1", "user_properties": { "item1": "value1", "item2": 2 } }], { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-1', 'event_properties': { 'item1': 'value1', 'item2': 1 } }, { 'user_id': 'user-2', 'event_type': 'event-2', 'event_properties': { 'item1': 'value2', 'item2': 2 } }], 'api_key': 'My-Key' }, { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-3', 'event_properties': { 'item1': 'value3', 'item2': 3 } }], 'api_key': 'My-Key' }, ] p.track("user-2", Event('event-4', Properties(item1='value4', item2=4))) p.track("user-1", Event('event-5', Properties(item1='value5', item2=5))) finally: p.shutdown() time.sleep(0.1) httpserver.stop() requests = _get_cleaned_requests(httpserver) assert requests == [ [{ "user_id": "user-1", "user_properties": { "item1": "value1", "item2": 2 } }], { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-1', 'event_properties': { 'item1': 'value1', 'item2': 1 } }, { 'user_id': 'user-2', 'event_type': 'event-2', 'event_properties': { 'item1': 'value2', 'item2': 2 } }], 'api_key': 'My-Key' }, { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-3', 'event_properties': { 'item1': 'value3', 'item2': 3 } }], 'api_key': 'My-Key' }, { 'events': [{ 'user_id': 'user-2', 'event_type': 'event-4', 'event_properties': { 'item1': 'value4', 'item2': 4 } }, { 'user_id': 'user-1', 'event_type': 'event-5', 'event_properties': { 'item1': 'value5', 'item2': 5 } }], 'api_key': 'My-Key' }, ]
post_page_expected_request = { 'type': 'page', 'properties': { 'item1': 'value3', 'item2': 3 }, 'valid': False, 'validation': { 'details': 'invalid!!!' } } # Valid Track Call Info post_track_1_args = [ "user-2", Event('event-1', Properties(item1='value1', item2=1)), [ ValidationResponse(valid=False, plugin_id='custom', message='not valid!!!'), ValidationResponse(valid=False, plugin_id='custom', message='invalid!!!'), ] ] post_track_1_expected_request = { 'type': 'track', 'properties': { 'item1': 'value1', 'item2': 1 },
def test_snowplow(httpserver: HTTPServer): httpserver.expect_request('/v1/batch').respond_with_data() endpoint = httpserver.url_for("").replace("http://", "") p = SnowplowPlugin("ly.iterative.test", SnowplowOptions(endpoint)) assert p.id() == 'snowplow' p.load(PluginLoadOptions(environment=Environment.DEVELOPMENT, logger=Logger.NONE)) p.page("user-1", "category-1", "page-1", Properties(item1='value0', item2=0)) p.track("user-2", Event('event-1', Properties(item1='value1', item2=1), id_="event-1", version="0.0.1")) p.flush() p.page("user-2", "category-2", "page-3", Properties(item1='value3', item2=3)) p.track("user-2", Event('event-4', Properties(item1='value4', item2=4), id_="event-4", version="0.0.4")) p.track("user-1", Event('event-5', Properties(item1='value5', item2=5), id_="event-5", version="0.0.5")) p.flush() p.shutdown() time.sleep(0.1) httpserver.stop() requests = _get_cleaned_requests(httpserver) assert requests == [ [ { 'properties': { 'data': { 'data': {'name': 'page-1'}, 'schema': 'iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0'}, 'schema': 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0' }, 'uid': 'user-1' }, { 'properties': { 'data': { 'data': {'item1': 'value1', 'item2': 1}, 'schema': 'iglu:ly.iterative.test/event-1/jsonschema/0-0-1' }, 'schema': 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0' }, 'uid': 'user-2' } ], [ { 'properties': { 'data': { 'data': {'name': 'page-3'}, 'schema': 'iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0' }, 'schema': 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0' }, 'uid': 'user-2' }, { 'properties': { 'data': { 'data': {'item1': 'value4', 'item2': 4}, 'schema': 'iglu:ly.iterative.test/event-4/jsonschema/0-0-4' }, 'schema': 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0' }, 'uid': 'user-2' }, { 'properties': { 'data': { 'data': {'item1': 'value5', 'item2': 5}, 'schema': 'iglu:ly.iterative.test/event-5/jsonschema/0-0-5' }, 'schema': 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0' }, 'uid': 'user-1' } ] ]
def test_segment(httpserver: HTTPServer): httpserver.expect_request('/v1/batch').respond_with_data() options = SegmentOptions(host=httpserver.url_for(''), ) p = SegmentPlugin('My-Key', options) assert p.id() == 'segment' p.load( PluginLoadOptions(environment=Environment.DEVELOPMENT, logger=Logger.NONE)) p.identify("user-1", Properties(item1='value1', item2=2)) p.alias("user-1", "prev-user-1") p.track("user-2", Event('event-1', Properties(item1='value1', item2=1))) p.group("user-2", "group-2", Properties(item1='value2', item2=2)) p.flush() p.page("user-2", "category-2", "page-3", Properties(item1='value3', item2=3)) p.track("user-2", Event('event-4', Properties(item1='value4', item2=4))) p.track("user-1", Event('event-5', Properties(item1='value5', item2=5))) p.flush() p.shutdown() time.sleep(0.1) httpserver.stop() requests = _get_cleaned_requests(httpserver) assert requests == [{ 'anonymousId': None, 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'integrations': {}, 'traits': { 'item1': 'value1', 'item2': 2 }, 'type': 'identify', 'userId': 'user-1' }, { 'anonymousId': None, 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'integrations': {}, 'previousId': 'prev-user-1', 'type': 'alias', 'userId': 'user-1' }, { 'anonymousId': None, 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'event': 'event-1', 'integrations': {}, 'properties': { 'item1': 'value1', 'item2': 1 }, 'type': 'track', 'userId': 'user-2' }, { 'anonymousId': None, 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'groupId': 'group-2', 'integrations': {}, 'traits': { 'item1': 'value2', 'item2': 2 }, 'type': 'group', 'userId': 'user-2' }, { 'anonymousId': None, 'category': 'category-2', 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'integrations': {}, 'name': 'page-3', 'properties': { 'item1': 'value3', 'item2': 3 }, 'type': 'page', 'userId': 'user-2' }, { 'anonymousId': None, 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'event': 'event-4', 'integrations': {}, 'properties': { 'item1': 'value4', 'item2': 4 }, 'type': 'track', 'userId': 'user-2' }, { 'anonymousId': None, 'context': { 'library': { 'name': 'analytics-python', 'version': '1.2.9' } }, 'event': 'event-5', 'integrations': {}, 'properties': { 'item1': 'value5', 'item2': 5 }, 'type': 'track', 'userId': 'user-1' }]