Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions common/djangoapps/track/views/segmentio.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,16 @@ def track_segmentio_event(request): # pylint: disable=too-many-statements
full_segment_event = request.json

# We mostly care about the properties
segment_properties = full_segment_event.get('properties', {})
segment_properties = _get_dict_value_with_default(full_segment_event, 'properties', {})

# Start with the context provided by Segment in the "client" field if it exists
# We should tightly control which fields actually get included in the event emitted.
segment_context = full_segment_event.get('context', {})
segment_context = _get_dict_value_with_default(full_segment_event, 'context', {})

# Build up the event context by parsing fields out of the event received from Segment
context = {}

library_name = segment_context.get('library', {}).get('name')
library_name = _get_dict_value_with_default(segment_context, 'library', {}).get('name')
source_map = getattr(settings, 'TRACKING_SEGMENTIO_SOURCE_MAP', {})
event_source = source_map.get(library_name)
if not event_source:
Expand Down Expand Up @@ -268,3 +268,12 @@ def _get_segmentio_event_name(event_properties):
def parse_iso8601_timestamp(timestamp):
"""Parse a particular type of ISO8601 formatted timestamp"""
return parser.parse(timestamp)


def _get_dict_value_with_default(dict_object, key, default):
"""
Returns default if the dict doesn't have the key or if the value is Falsey.
Otherwise, returns the dict's value for the key.
"""
value = dict_object.get(key, None)
return value if value else default
8 changes: 8 additions & 0 deletions common/djangoapps/track/views/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ def post_segmentio_event(self, **kwargs):
)
segmentio.track_segmentio_event(request)

def post_modified_segmentio_event(self, event):
"""Post an externally-defined fake Segment event to the view that processes it"""
request = self.create_request(
data=json.dumps(event),
content_type='application/json'
)
segmentio.track_segmentio_event(request)

def create_segmentio_event(self, **kwargs):
"""Populate a fake Segment event with data of interest"""
action = kwargs.get('action', 'Track')
Expand Down
64 changes: 40 additions & 24 deletions common/djangoapps/track/views/tests/test_segmentio.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,46 @@ def test_segmentio_ignore_actions(self, action):
self.post_segmentio_event(action=action)
self.assert_no_events_emitted()

def test_segmentio_ignore_missing_context_entry(self):
sample_event_raw = self.create_segmentio_event()
del sample_event_raw['context']
self.post_modified_segmentio_event(sample_event_raw)
self.assert_no_events_emitted()

def test_segmentio_ignore_null_context_entry(self):
sample_event_raw = self.create_segmentio_event()
sample_event_raw['context'] = None
self.post_modified_segmentio_event(sample_event_raw)
self.assert_no_events_emitted()

def test_segmentio_ignore_missing_library_entry(self):
sample_event_raw = self.create_segmentio_event()
del sample_event_raw['context']['library']
self.post_modified_segmentio_event(sample_event_raw)
self.assert_no_events_emitted()

def test_segmentio_ignore_null_library_entry(self):
sample_event_raw = self.create_segmentio_event()
sample_event_raw['context']['library'] = None
self.post_modified_segmentio_event(sample_event_raw)
self.assert_no_events_emitted()

def test_segmentio_ignore_unknown_libraries(self):
self.post_segmentio_event(library_name='foo')
self.assert_no_events_emitted()

@expect_failure_with_message(segmentio.ERROR_MISSING_NAME)
def test_segmentio_ignore_missing_properties_entry(self):
sample_event_raw = self.create_segmentio_event()
del sample_event_raw['properties']
self.post_modified_segmentio_event(sample_event_raw)

@expect_failure_with_message(segmentio.ERROR_MISSING_NAME)
def test_segmentio_ignore_null_properties_entry(self):
sample_event_raw = self.create_segmentio_event()
sample_event_raw['properties'] = None
self.post_modified_segmentio_event(sample_event_raw)

@expect_failure_with_message(segmentio.ERROR_USER_NOT_EXIST)
def test_no_user_for_user_id(self):
self.post_segmentio_event(user_id=40)
Expand Down Expand Up @@ -148,43 +184,23 @@ def test_invalid_course_id(self):
def test_missing_name(self):
sample_event_raw = self.create_segmentio_event()
del sample_event_raw['properties']['name']
request = self.create_request(
data=json.dumps(sample_event_raw),
content_type='application/json'
)

segmentio.track_segmentio_event(request)
self.post_modified_segmentio_event(sample_event_raw)

@expect_failure_with_message(segmentio.ERROR_MISSING_DATA)
def test_missing_data(self):
sample_event_raw = self.create_segmentio_event()
del sample_event_raw['properties']['data']
request = self.create_request(
data=json.dumps(sample_event_raw),
content_type='application/json'
)

segmentio.track_segmentio_event(request)
self.post_modified_segmentio_event(sample_event_raw)

@expect_failure_with_message(segmentio.ERROR_MISSING_TIMESTAMP)
def test_missing_timestamp(self):
sample_event_raw = self.create_event_without_fields('timestamp')
request = self.create_request(
data=json.dumps(sample_event_raw),
content_type='application/json'
)

segmentio.track_segmentio_event(request)
self.post_modified_segmentio_event(sample_event_raw)

@expect_failure_with_message(segmentio.ERROR_MISSING_RECEIVED_AT)
def test_missing_received_at(self):
sample_event_raw = self.create_event_without_fields('receivedAt')
request = self.create_request(
data=json.dumps(sample_event_raw),
content_type='application/json'
)

segmentio.track_segmentio_event(request)
self.post_modified_segmentio_event(sample_event_raw)

def create_event_without_fields(self, *fields):
"""Create a fake event and remove some fields from it"""
Expand Down