Esempio n. 1
0
class TrackMiddlewareTestCase(TestCase):

    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

    def test_normal_request(self, mock_server_track):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)

    def test_default_filters_do_not_render_view(self, mock_server_track):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(mock_server_track.called)
            mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self, mock_server_track):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self, mock_server_track):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)
        mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(mock_server_track.called)
Esempio n. 2
0
    def test_user_track_with_middleware(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get('/event', {
            'page': self.url_with_course,
            'event_type': sentinel.event_type,
            'event': {}
        })
        middleware.process_request(request)
        try:
            views.user_track(request)

            expected_event = {
                'username': '******',
                'session': '',
                'ip': '127.0.0.1',
                'event_source': 'browser',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': self.url_with_course,
                'time': expected_time,
                'host': 'testserver',
                'context': {
                    'course_id': 'foo/bar/baz',
                    'org_id': 'foo',
                    'user_id': '',
                    'path': u'/event'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)
Esempio n. 3
0
    def test_server_track_with_middleware(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get(self.path_with_course)
        middleware.process_request(request)
        # The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
        self.mock_tracker.reset_mock()
        try:
            views.server_track(request, str(sentinel.event_type), '{}')

            expected_event = {
                'username': '******',
                'ip': '127.0.0.1',
                'event_source': 'server',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': None,
                'time': expected_time,
                'host': 'testserver',
                'context': {
                    'user_id': '',
                    'course_id': u'foo/bar/baz',
                    'org_id': 'foo',
                    'path': u'/courses/foo/bar/baz/xmod/'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)
class TrackMiddlewareTestCase(TestCase):
    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

    def test_normal_request(self, mock_server_track):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)

    def test_default_filters_do_not_render_view(self, mock_server_track):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(mock_server_track.called)
            mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self, mock_server_track):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self, mock_server_track):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)
        mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(mock_server_track.called)
Esempio n. 5
0
    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)
Esempio n. 6
0
    def test_server_track_with_middleware_and_google_analytics_cookie(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get(self.path_with_course)
        request.COOKIES['_ga'] = 'GA1.2.1033501218.1368477899'
        middleware.process_request(request)
        # The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
        self.mock_tracker.reset_mock()
        try:
            views.server_track(request, str(sentinel.event_type), '{}')

            expected_event = {
                'accept_language': '',
                'referer': '',
                'username': '******',
                'ip': '127.0.0.1',
                'event_source': 'server',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': None,
                'time': FROZEN_TIME,
                'host': 'testserver',
                'context': {
                    'user_id': '',
                    'course_id': u'foo/bar/baz',
                    'org_id': 'foo',
                    'path': u'/courses/foo/bar/baz/xmod/'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.assert_mock_tracker_call_matches(expected_event)
Esempio n. 7
0
    def test_success(self, course_id):
        middleware = TrackMiddleware()

        request = self.create_request(
            data=self.create_segmentio_event_json(data={'foo': 'bar'}, course_id=course_id),
            content_type='application/json'
        )
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        # The middleware normally emits an event, make sure it doesn't in this case.
        self.assert_no_events_emitted()
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'accept_language': '',
                'referer': '',
                'username': str(sentinel.username),
                'ip': '',
                'session': '',
                'event_source': 'mobile',
                'event_type': str(sentinel.name),
                'name': str(sentinel.name),
                'event': {'foo': 'bar'},
                'agent': str(sentinel.user_agent),
                'page': None,
                'time': datetime.strptime("2014-08-27T16:33:39.215Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host': 'testserver',
                'context': {
                    'application': {
                        'name': 'edx.mobile.android',
                        'version': '1.0.1',
                    },
                    'user_id': USER_ID,
                    'course_id': course_id,
                    'org_id': u'foo',
                    'path': ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'received_at': datetime.strptime("2014-08-27T16:33:39.100Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
            }
        finally:
            middleware.process_response(request, None)

        assert_event_matches(expected_event, self.get_event())
Esempio n. 8
0
    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)
Esempio n. 9
0
    def test_user_track_with_middleware_and_processors(self):
        self.recreate_tracker()

        middleware = TrackMiddleware()
        payload = '{"foo": "bar"}'
        user_id = 1
        request = self.request_factory.get('/event', {
            'page': self.url_with_course,
            'event_type': sentinel.event_type,
            'event': payload
        })
        request.user = User.objects.create(pk=user_id, username=str(sentinel.username))
        request.META['REMOTE_ADDR'] = '10.0.0.1'
        request.META['HTTP_REFERER'] = str(sentinel.referer)
        request.META['HTTP_ACCEPT_LANGUAGE'] = str(sentinel.accept_language)
        request.META['HTTP_USER_AGENT'] = str(sentinel.user_agent)
        request.META['SERVER_NAME'] = 'testserver2'
        middleware.process_request(request)
        try:
            views.user_track(request)

            expected_event = {
                'accept_language': str(sentinel.accept_language),
                'referer': str(sentinel.referer),
                'username': str(sentinel.username),
                'session': '',
                'ip': '10.0.0.1',
                'event_source': 'browser',
                'event_type': str(sentinel.event_type),
                'name': str(sentinel.event_type),
                'event': payload,
                'agent': str(sentinel.user_agent),
                'page': self.url_with_course,
                'time': FROZEN_TIME,
                'host': 'testserver2',
                'context': {
                    'course_id': 'foo/bar/baz',
                    'org_id': 'foo',
                    'user_id': user_id,
                    'path': u'/event'
                },
            }
        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event, actual_event)
    def setUp(self):
        super(TrackMiddlewareTestCase, self).setUp()
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch("track.views.server_track")
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)
Esempio n. 11
0
    def test_success(self, course_id):
        middleware = TrackMiddleware()

        request = self.create_request(
            data=self.create_segmentio_event_json(event_type=str(sentinel.event_type), event={'foo': 'bar'}, course_id=course_id),
            content_type='application/json'
        )
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        # The middleware normally emits an event, make sure it doesn't in this case.
        self.assertFalse(self.mock_tracker.send.called)  # pylint: disable=maybe-no-member
        try:
            response = segmentio.track_segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'username': str(sentinel.username),
                'ip': '',
                'event_source': 'mobile',
                'event_type': str(sentinel.event_type),
                'name': str(sentinel.name),
                'event': {'foo': 'bar'},
                'agent': str(sentinel.user_agent),
                'page': None,
                'time': datetime.strptime("2014-08-27T16:33:39.215Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host': 'testserver',
                'context': {
                    'user_id': USER_ID,
                    'course_id': course_id,
                    'org_id': 'foo',
                    'path': ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'unknown',
                            'version': 'unknown'
                        },
                        'userAgent': str(sentinel.user_agent)
                    },
                    'received_at': datetime.strptime("2014-08-27T16:33:39.100Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)  # pylint: disable=maybe-no-member
Esempio n. 12
0
    def test_user_track_with_middleware(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get('/event', {
            'page': self.url_with_course,
            'event_type': sentinel.event_type,
            'event': {}
        })
        middleware.process_request(request)
        try:
            views.user_track(request)

            expected_event = {
                'username': '******',
                'session': '',
                'ip': '127.0.0.1',
                'event_source': 'browser',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': self.url_with_course,
                'time': expected_time,
                'host': 'testserver',
                'context': {
                    'course_id': 'foo/bar/baz',
                    'org_id': 'foo',
                    'user_id': '',
                    'path': u'/event'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)
    def test_server_track_with_middleware(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get(self.path_with_course)
        middleware.process_request(request)
        # The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
        self.mock_tracker.reset_mock()
        try:
            views.server_track(request, str(sentinel.event_type), '{}')

            expected_event = {
                'accept_language': '',
                'referer': '',
                'username': '******',
                'ip': '127.0.0.1',
                'event_source': 'server',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': None,
                'time': FROZEN_TIME,
                'host': 'testserver',
                'context': {
                    'user_id': '',
                    'course_id': u'foo/bar/baz',
                    'org_id': 'foo',
                    'path': u'/courses/foo/bar/baz/xmod/'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.assert_mock_tracker_call_matches(expected_event)
Esempio n. 14
0
    def test_server_track_with_middleware_and_google_analytics_cookie(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get(self.path_with_course)
        request.COOKIES['_ga'] = 'GA1.2.1033501218.1368477899'
        middleware.process_request(request)
        # The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
        self.mock_tracker.reset_mock()
        try:
            views.server_track(request, str(sentinel.event_type), '{}')

            expected_event = {
                'username': '******',
                'ip': '127.0.0.1',
                'event_source': 'server',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': None,
                'time': expected_time,
                'host': 'testserver',
                'context': {
                    'user_id': '',
                    'course_id': u'foo/bar/baz',
                    'org_id': 'foo',
                    'path': u'/courses/foo/bar/baz/xmod/'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)
Esempio n. 15
0
    def test_user_track_with_middleware(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get('/event', {
            'page': self.url_with_course,
            'event_type': sentinel.event_type,
            'event': {}
        })
        request.user = self.user
        request.session = {"referer": "www.baidu.com"}
        middleware.process_request(request)
        try:
            views.user_track(request)

            expected_event = {
                'username': '',
                'session': None,
                'ip': '127.0.0.1',
                'event_source': 'browser',
                'event_type': str(sentinel.event_type),
                'event': {},
                'agent': '',
                'page': self.url_with_course,
                'time': '2013/10/03 16:24:55',
                'host': 'testserver',
                'spam': None,
                'referer': '',
                'origin_referer': 'www.baidu.com',
                'context': {
                    'course_id': 'foo/bar/baz',
                    'org_id': 'foo',
                    'user_id': '',
                    'path': u'/event'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)
Esempio n. 16
0
    def test_server_track_with_middleware_and_google_analytics_cookie(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get(self.path_with_course)
        request.COOKIES['_ga'] = 'GA1.2.1033501218.1368477899'
        request.user = self.user
        request.session = {"referer": "www.baidu.com"}
        middleware.process_request(request)
        # The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
        self.mock_tracker.reset_mock()
        try:
            views.server_track(request, str(sentinel.event_type), '{}')

            expected_event = {
                'username': '',
                'ip': '127.0.0.1',
                'event_source': 'server',
                'event_type': str(sentinel.event_type),
                'event': '{}',
                'agent': '',
                'page': None,
                'time': '2013/10/03 16:24:55',
                'host': 'testserver',
                'session': None,
                'referer': '',
                'origin_referer': 'www.baidu.com',
                'spam': None,
                'method': 'GET',
                'context': {
                    'user_id': '',
                    'course_id': u'foo/bar/baz',
                    'org_id': 'foo',
                    'path': u'/courses/foo/bar/baz/xmod/'
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)
Esempio n. 17
0
    def test_success(self, course_id):
        middleware = TrackMiddleware()

        request = self.create_request(
            data=self.create_segmentio_event_json(data={'foo': 'bar'}, course_id=course_id),
            content_type='application/json'
        )
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        # The middleware normally emits an event, make sure it doesn't in this case.
        self.assert_no_events_emitted()
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'accept_language': '',
                'referer': '',
                'username': str(sentinel.username),
                'ip': '',
                'session': '',
                'event_source': 'mobile',
                'event_type': str(sentinel.name),
                'name': str(sentinel.name),
                'event': {'foo': 'bar'},
                'agent': str(sentinel.user_agent),
                'page': None,
                'time': datetime.strptime("2014-08-27T16:33:39.215Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host': 'testserver',
                'context': {
                    'application': {
                        'name': 'edx.mobile.android',
                        'version': '1.0.1',
                    },
                    'user_id': USER_ID,
                    'course_id': course_id,
                    'org_id': u'foo',
                    'path': ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'received_at': datetime.strptime("2014-08-27T16:33:39.100Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
            }
        finally:
            middleware.process_response(request, None)

        assert_event_matches(expected_event, self.get_event())
Esempio n. 18
0
    def test_user_track_with_middleware_and_processors(self):
        self.recreate_tracker()

        middleware = TrackMiddleware()
        payload = '{"foo": "bar"}'
        user_id = 1
        request = self.request_factory.get(
            '/event', {
                'page': self.url_with_course,
                'event_type': sentinel.event_type,
                'event': payload
            })
        request.user = User.objects.create(pk=user_id,
                                           username=str(sentinel.username))
        request.META['REMOTE_ADDR'] = '10.0.0.1'
        request.META['HTTP_REFERER'] = str(sentinel.referer)
        request.META['HTTP_ACCEPT_LANGUAGE'] = str(sentinel.accept_language)
        request.META['HTTP_USER_AGENT'] = str(sentinel.user_agent)
        request.META['SERVER_NAME'] = 'testserver2'
        middleware.process_request(request)
        try:
            views.user_track(request)

            expected_event = {
                'accept_language': str(sentinel.accept_language),
                'referer': str(sentinel.referer),
                'username': str(sentinel.username),
                'session': '',
                'ip': '10.0.0.1',
                'event_source': 'browser',
                'event_type': str(sentinel.event_type),
                'name': str(sentinel.event_type),
                'event': payload,
                'agent': str(sentinel.user_agent),
                'page': self.url_with_course,
                'time': FROZEN_TIME,
                'host': 'testserver2',
                'context': {
                    'course_id': 'foo/bar/baz',
                    'org_id': 'foo',
                    'user_id': user_id,
                    'path': u'/event'
                },
            }
        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event, actual_event)
Esempio n. 19
0
    def test_server_track_with_middleware_and_google_analytics_cookie(self):
        middleware = TrackMiddleware()
        request = self.request_factory.get(self.path_with_course)
        request.COOKIES['_ga'] = 'GA1.2.1033501218.1368477899'
        middleware.process_request(request)
        # The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
        self.mock_tracker.reset_mock()
        try:
            views.server_track(request, str(sentinel.event_type), '{}')

            expected_event = {
                'timestamp': FROZEN_TIME,
                'data': '{"GET": {}, "POST": {}}',
                'name': self.path_with_course,
                'context': {
                    'username': '******',
                    'user_id': '',
                    'accept_language': '',
                    'ip': '127.0.0.1',
                    'org_id': 'foo',
                    'agent': '',
                    'event_source': 'server',
                    'host': 'testserver',
                    'session': '',
                    'referer': '',
                    'client_id': '1033501218.1368477899',
                    'course_id': 'foo/bar/baz',
                    'path': self.path_with_course,
                    'page': None
                }
            }

        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event,
                             actual_event,
                             tolerate={
                                 'string_payload',
                             })
Esempio n. 20
0
class TrackMiddlewareTestCase(TestCase):

    def setUp(self):
        super(TrackMiddlewareTestCase, self).setUp()
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path('/courses/')
        self.assertEquals(context, {
            'accept_language': '',
            'referer': '',
            'user_id': '',
            'session': '',
            'username': '',
            'ip': '127.0.0.1',
            'host': 'testserver',
            'agent': '',
            'path': '/courses/',
            'org_id': '',
            'course_id': '',
            'client_id': None,
        })

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(
            tracker.get_tracker().resolve_context(),
            {}
        )

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path('/courses/test_org/test_course/test_run/foo')
        expected_context_subset = {
            'course_id': 'test_org/test_course/test_run',
            'org_id': 'test_org',
        }
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get('/courses/')
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'user_id': user_id,
            'username': username,
        })

    def test_request_with_session(self):
        request = self.request_factory.get('/courses/')
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key
        expected_session_key = self.track_middleware.encrypt_session_key(session_key)
        self.assertEquals(len(session_key), len(expected_session_key))
        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'session': expected_session_key,
        })

    @override_settings(SECRET_KEY='85920908f28904ed733fe576320db18cabd7b6cd')
    def test_session_key_encryption(self):
        session_key = '665924b49a93e22b46ee9365abf28c2a'
        expected_session_key = '3b81f559d14130180065d635a4f35dd2'
        encrypted_session_key = self.track_middleware.encrypt_session_key(session_key)
        self.assertEquals(encrypted_session_key, expected_session_key)

    def test_request_headers(self):
        ip_address = '10.0.0.0'
        user_agent = 'UnitTest/1.0'

        factory = RequestFactory(REMOTE_ADDR=ip_address, HTTP_USER_AGENT=user_agent)
        request = factory.get('/some-path')
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {
            'ip': ip_address,
            'agent': user_agent,
        })

    @patch('track.middleware.TRUNCATION_LENGTH', 6)
    def test_student_answer_request(self):
        request = self.request_factory.post('/dummy')
        request.POST = {'student_answer': ['firstanswer', 'secondanswer']}
        self.track_middleware.process_request(request)
        event = '{"POST": {"student_answer": ["fir", "sec"]}, "GET": {}}'
        self.mock_server_track.assert_called_with(request, request.META['PATH_INFO'], event)

    @patch('track.middleware.TRUNCATION_LENGTH', 20)
    def test_submission_request(self):
        request = self.request_factory.post('/dummy')
        request.POST = {'{"submission":["first open response", "second open response"]}': []}
        self.track_middleware.process_request(request)
        event = '{"POST": {"submission": ["first open", "second ope"]}, "GET": {}}'
        self.mock_server_track.assert_called_with(request, request.META['PATH_INFO'], event)
Esempio n. 21
0
class TrackMiddlewareTestCase(TestCase):

    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path('/courses/')
        self.assertEquals(context, {
            'user_id': '',
            'session': '',
            'username': '',
            'ip': '127.0.0.1',
            'host': 'testserver',
            'agent': '',
            'path': '/courses/',
            'org_id': '',
            'course_id': '',
        })

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(
            tracker.get_tracker().resolve_context(),
            {}
        )

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path('/courses/test_org/test_course/test_run/foo')
        expected_context_subset = {
            'course_id': 'test_org/test_course/test_run',
            'org_id': 'test_org',
        }
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get('/courses/')
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'user_id': user_id,
            'username': username,
        })

    def test_request_with_session(self):
        request = self.request_factory.get('/courses/')
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'session': session_key,
        })

    def test_request_headers(self):
        ip_address = '10.0.0.0'
        user_agent = 'UnitTest/1.0'

        factory = RequestFactory(REMOTE_ADDR=ip_address, HTTP_USER_AGENT=user_agent)
        request = factory.get('/some-path')
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {
            'ip': ip_address,
            'agent': user_agent,
        })
Esempio n. 22
0
    def test_video_event(self, name, event_type):
        course_id = 'foo/bar/baz'
        middleware = TrackMiddleware()

        input_payload = {
            'current_time': 132.134456,
            'module_id': 'i4x://foo/bar/baz/some_module',
            'code': 'mobile'
        }
        if name == 'edx.video.loaded':
            del input_payload['current_time']

        request = self.create_request(
            data=self.create_segmentio_event_json(
                name=name,
                data=input_payload,
                open_in_browser_url='https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity/2',
                context={
                    'course_id': course_id,
                    'application': {
                        'name': 'edx.mobileapp.android',
                        'version': '29',
                        'component': 'videoplayer'
                    }
                }),
            content_type='application/json'
        )
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event_without_payload = {
                'username': str(sentinel.username),
                'ip': '',
                'session': '',
                'event_source': 'mobile',
                'event_type': event_type,
                'name': name,
                'agent': str(sentinel.user_agent),
                'page': 'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity',
                'time': datetime.strptime("2014-08-27T16:33:39.215Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host': 'testserver',
                'context': {
                    'user_id': USER_ID,
                    'course_id': course_id,
                    'org_id': 'foo',
                    'path': ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'application': {
                            'name': 'edx.mobileapp.android',
                            'version': '29',
                            'component': 'videoplayer'
                        }
                    },
                    'received_at': datetime.strptime("2014-08-27T16:33:39.100Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
            }
            expected_payload = {
                'currentTime': 132.134456,
                'id': 'i4x-foo-bar-baz-some_module',
                'code': 'mobile'
            }
            if name == 'edx.video.loaded':
                del expected_payload['currentTime']
        finally:
            middleware.process_response(request, None)

        actual_event = dict(self.get_event())
        payload = json.loads(actual_event.pop('event'))

        self.assertEquals(actual_event, expected_event_without_payload)
        self.assertEquals(payload, expected_payload)
Esempio n. 23
0
    def test_success(self, course_id):
        middleware = TrackMiddleware()

        request = self.create_request(data=self.create_segmentio_event_json(
            event_type=str(sentinel.event_type),
            event={'foo': 'bar'},
            course_id=course_id),
                                      content_type='application/json')
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        # The middleware normally emits an event, make sure it doesn't in this case.
        self.assertFalse(self.mock_tracker.send.called)  # pylint: disable=maybe-no-member
        try:
            response = segmentio.track_segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'username':
                str(sentinel.username),
                'ip':
                '',
                'event_source':
                'mobile',
                'event_type':
                str(sentinel.event_type),
                'name':
                str(sentinel.name),
                'event': {
                    'foo': 'bar'
                },
                'agent':
                str(sentinel.user_agent),
                'page':
                None,
                'time':
                datetime.strptime("2014-08-27T16:33:39.215Z",
                                  "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host':
                'testserver',
                'context': {
                    'user_id':
                    USER_ID,
                    'course_id':
                    course_id,
                    'org_id':
                    'foo',
                    'path':
                    ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'unknown',
                            'version': 'unknown'
                        },
                        'userAgent': str(sentinel.user_agent)
                    },
                    'received_at':
                    datetime.strptime("2014-08-27T16:33:39.100Z",
                                      "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
            }
        finally:
            middleware.process_response(request, None)

        self.mock_tracker.send.assert_called_once_with(expected_event)  # pylint: disable=maybe-no-member
Esempio n. 24
0
class TrackMiddlewareTestCase(TestCase):
    """  Class for checking tracking requests """

    def setUp(self):
        super(TrackMiddlewareTestCase, self).setUp()
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @ddt.unpack
    @ddt.data(
        ('HTTP_USER_AGENT', 'agent'),
        ('PATH_INFO', 'path'),
        ('HTTP_REFERER', 'referer'),
        ('HTTP_ACCEPT_LANGUAGE', 'accept_language'),
    )
    def test_request_with_latin1_characters(self, meta_key, context_key):
        """
        When HTTP headers contains latin1 characters.
        """
        request = self.request_factory.get('/somewhere')
        # pylint: disable=no-member
        request.META[meta_key] = 'test latin1 \xd3 \xe9 \xf1'  # pylint: disable=no-member

        context = self.get_context_for_request(request)
        # The bytes in the string on the right are utf8 encoded in the source file, so we decode them to construct
        # a valid unicode string.
        self.assertEqual(context[context_key], 'test latin1 Ó é ñ'.decode('utf8'))

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path('/courses/')
        self.assertEquals(context, {
            'accept_language': '',
            'referer': '',
            'user_id': '',
            'session': '',
            'username': '',
            'ip': '127.0.0.1',
            'host': 'testserver',
            'agent': '',
            'path': '/courses/',
            'org_id': '',
            'course_id': '',
            'client_id': None,
        })

    def test_no_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'

        request.META['REMOTE_ADDR'] = remote_addr
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], remote_addr)

    def test_single_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'
        forwarded_ip = '11.22.33.44'

        request.META['REMOTE_ADDR'] = remote_addr
        request.META['HTTP_X_FORWARDED_FOR'] = forwarded_ip
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], forwarded_ip)

    def test_multiple_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'
        forwarded_ip = '11.22.33.44, 10.0.0.1, 127.0.0.1'

        request.META['REMOTE_ADDR'] = remote_addr
        request.META['HTTP_X_FORWARDED_FOR'] = forwarded_ip
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], '11.22.33.44')

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(
            tracker.get_tracker().resolve_context(),
            {}
        )

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path('/courses/test_org/test_course/test_run/foo')
        expected_context_subset = {
            'course_id': 'test_org/test_course/test_run',
            'org_id': 'test_org',
        }
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get('/courses/')
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'user_id': user_id,
            'username': username,
        })

    def test_request_with_session(self):
        request = self.request_factory.get('/courses/')
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key
        expected_session_key = self.track_middleware.encrypt_session_key(session_key)
        self.assertEquals(len(session_key), len(expected_session_key))
        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'session': expected_session_key,
        })

    @override_settings(SECRET_KEY='85920908f28904ed733fe576320db18cabd7b6cd')
    def test_session_key_encryption(self):
        session_key = '665924b49a93e22b46ee9365abf28c2a'
        expected_session_key = '3b81f559d14130180065d635a4f35dd2'
        encrypted_session_key = self.track_middleware.encrypt_session_key(session_key)
        self.assertEquals(encrypted_session_key, expected_session_key)

    def test_request_headers(self):
        ip_address = '10.0.0.0'
        user_agent = 'UnitTest/1.0'
        client_id_header = '123.123'

        factory = RequestFactory(
            REMOTE_ADDR=ip_address, HTTP_USER_AGENT=user_agent, HTTP_X_EDX_GA_CLIENT_ID=client_id_header
        )
        request = factory.get('/some-path')
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {
            'ip': ip_address,
            'agent': user_agent,
            'client_id': client_id_header
        })

    @patch('track.middleware.TRUNCATION_LENGTH', 6)
    def test_student_answer_request(self):
        request = self.request_factory.post('/dummy')
        request.POST = {'student_answer': ['firstanswer', 'secondanswer']}
        self.track_middleware.process_request(request)
        event = '{"POST": {"student_answer": ["fir", "sec"]}, "GET": {}}'
        self.mock_server_track.assert_called_with(request, request.META['PATH_INFO'], event)

    @patch('track.middleware.TRUNCATION_LENGTH', 20)
    def test_submission_request(self):
        request = self.request_factory.post('/dummy')
        request.POST = {'{"submission":["first open response", "second open response"]}': []}
        self.track_middleware.process_request(request)
        event = '{"POST": {"submission": ["first open", "second ope"]}, "GET": {}}'
        self.mock_server_track.assert_called_with(request, request.META['PATH_INFO'], event)
Esempio n. 25
0
 def setUp(self):
     self.track_middleware = TrackMiddleware()
     self.request_factory = RequestFactory()
Esempio n. 26
0
class TrackMiddlewareTestCase(TestCase):
    def setUp(self):
        super(TrackMiddlewareTestCase, self).setUp()
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path('/courses/')
        self.assertEquals(
            context, {
                'accept_language': '',
                'referer': '',
                'user_id': '',
                'session': '',
                'username': '',
                'ip': '127.0.0.1',
                'host': 'testserver',
                'agent': '',
                'path': '/courses/',
                'org_id': '',
                'course_id': '',
                'client_id': None,
            })

    def test_no_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'

        request.META['REMOTE_ADDR'] = remote_addr
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], remote_addr)

    def test_single_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'
        forwarded_ip = '11.22.33.44'

        request.META['REMOTE_ADDR'] = remote_addr
        request.META['HTTP_X_FORWARDED_FOR'] = forwarded_ip
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], forwarded_ip)

    def test_multiple_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'
        forwarded_ip = '11.22.33.44, 10.0.0.1, 127.0.0.1'

        request.META['REMOTE_ADDR'] = remote_addr
        request.META['HTTP_X_FORWARDED_FOR'] = forwarded_ip
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], '11.22.33.44')

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(tracker.get_tracker().resolve_context(), {})

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path(
            '/courses/test_org/test_course/test_run/foo')
        expected_context_subset = {
            'course_id': 'test_org/test_course/test_run',
            'org_id': 'test_org',
        }
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get('/courses/')
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'user_id': user_id,
            'username': username,
        })

    def test_request_with_session(self):
        request = self.request_factory.get('/courses/')
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key
        expected_session_key = self.track_middleware.encrypt_session_key(
            session_key)
        self.assertEquals(len(session_key), len(expected_session_key))
        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'session': expected_session_key,
        })

    @override_settings(SECRET_KEY='85920908f28904ed733fe576320db18cabd7b6cd')
    def test_session_key_encryption(self):
        session_key = '665924b49a93e22b46ee9365abf28c2a'
        expected_session_key = '3b81f559d14130180065d635a4f35dd2'
        encrypted_session_key = self.track_middleware.encrypt_session_key(
            session_key)
        self.assertEquals(encrypted_session_key, expected_session_key)

    def test_request_headers(self):
        ip_address = '10.0.0.0'
        user_agent = 'UnitTest/1.0'
        client_id_header = '123.123'

        factory = RequestFactory(REMOTE_ADDR=ip_address,
                                 HTTP_USER_AGENT=user_agent,
                                 HTTP_X_EDX_GA_CLIENT_ID=client_id_header)
        request = factory.get('/some-path')
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {
            'ip': ip_address,
            'agent': user_agent,
            'client_id': client_id_header
        })
class TrackMiddlewareTestCase(TestCase):
    def setUp(self):
        super(TrackMiddlewareTestCase, self).setUp()
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch("track.views.server_track")
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get("/somewhere")
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    def test_default_filters_do_not_render_view(self):
        for url in ["/event", "/event/1", "/login", "/heartbeat"]:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get("/event")
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r"^/some/excluded.*"])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get("/excluded")
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get("/some/excluded/url")
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path("/courses/")
        self.assertEquals(
            context,
            {
                "accept_language": "",
                "referer": "",
                "user_id": "",
                "session": "",
                "username": "",
                "ip": "127.0.0.1",
                "host": "testserver",
                "agent": "",
                "path": "/courses/",
                "org_id": "",
                "course_id": "",
                "client_id": None,
            },
        )

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(tracker.get_tracker().resolve_context(), {})

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path("/courses/test_org/test_course/test_run/foo")
        expected_context_subset = {"course_id": "test_org/test_course/test_run", "org_id": "test_org"}
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get("/courses/")
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {"user_id": user_id, "username": username})

    def test_request_with_session(self):
        request = self.request_factory.get("/courses/")
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key
        expected_session_key = self.track_middleware.encrypt_session_key(session_key)
        self.assertEquals(len(session_key), len(expected_session_key))
        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {"session": expected_session_key})

    @override_settings(SECRET_KEY="85920908f28904ed733fe576320db18cabd7b6cd")
    def test_session_key_encryption(self):
        session_key = "665924b49a93e22b46ee9365abf28c2a"
        expected_session_key = "3b81f559d14130180065d635a4f35dd2"
        encrypted_session_key = self.track_middleware.encrypt_session_key(session_key)
        self.assertEquals(encrypted_session_key, expected_session_key)

    def test_request_headers(self):
        ip_address = "10.0.0.0"
        user_agent = "UnitTest/1.0"

        factory = RequestFactory(REMOTE_ADDR=ip_address, HTTP_USER_AGENT=user_agent)
        request = factory.get("/some-path")
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {"ip": ip_address, "agent": user_agent})
Esempio n. 28
0
    def test_video_event(self, name, event_type):
        course_id = 'foo/bar/baz'
        middleware = TrackMiddleware()

        input_payload = {
            'current_time': 132.134456,
            'module_id': 'i4x://foo/bar/baz/some_module',
            'code': 'mobile'
        }
        if name == 'edx.video.loaded':
            # We use the same expected payload for all of these types of events, but the load video event is the only
            # one that is not actually expected to contain a "current time" field. So we remove it from the expected
            # event here.
            del input_payload['current_time']

        request = self.create_request(
            data=self.create_segmentio_event_json(
                name=name,
                data=input_payload,
                context={
                    'open_in_browser_url': 'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity/2',
                    'course_id': course_id,
                    'application': {
                        'name': 'edx.mobileapp.android',
                        'version': '29',
                        'component': 'videoplayer'
                    }
                }),
            content_type='application/json'
        )
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'accept_language': '',
                'referer': '',
                'username': str(sentinel.username),
                'ip': '',
                'session': '',
                'event_source': 'mobile',
                'event_type': event_type,
                'name': name,
                'agent': str(sentinel.user_agent),
                'page': 'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity',
                'time': datetime.strptime("2014-08-27T16:33:39.215Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host': 'testserver',
                'context': {
                    'user_id': USER_ID,
                    'course_id': course_id,
                    'org_id': 'foo',
                    'path': ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'application': {
                        'name': 'edx.mobileapp.android',
                        'version': '29',
                        'component': 'videoplayer'
                    },
                    'received_at': datetime.strptime("2014-08-27T16:33:39.100Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
                'event': {
                    'currentTime': 132.134456,
                    'id': 'i4x-foo-bar-baz-some_module',
                    'code': 'mobile'
                }
            }
            if name == 'edx.video.loaded':
                # We use the same expected payload for all of these types of events, but the load video event is the
                # only one that is not actually expected to contain a "current time" field. So we remove it from the
                # expected event here.
                del expected_event['event']['currentTime']
        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event, actual_event)
Esempio n. 29
0
    def test_video_event(self, name, event_type):
        course_id = 'foo/bar/baz'
        middleware = TrackMiddleware()

        input_payload = {
            'current_time': 132.134456,
            'module_id': 'i4x://foo/bar/baz/some_module',
            'code': 'mobile'
        }
        if name == 'edx.video.loaded':
            # We use the same expected payload for all of these types of events, but the load video event is the only
            # one that is not actually expected to contain a "current time" field. So we remove it from the expected
            # event here.
            del input_payload['current_time']

        request = self.create_request(data=self.create_segmentio_event_json(
            name=name,
            data=input_payload,
            context={
                'open_in_browser_url':
                'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity/2',
                'course_id': course_id,
                'application': {
                    'name': 'edx.mobileapp.android',
                    'version': '29',
                    'component': 'videoplayer'
                }
            }),
                                      content_type='application/json')
        User.objects.create(pk=SEGMENTIO_TEST_USER_ID,
                            username=str(sentinel.username))

        middleware.process_request(request)
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'accept_language':
                '',
                'referer':
                '',
                'username':
                str(sentinel.username),
                'ip':
                '',
                'session':
                '',
                'event_source':
                'mobile',
                'event_type':
                event_type,
                'name':
                name,
                'agent':
                str(sentinel.user_agent),
                'page':
                'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity',
                'time':
                datetime.strptime("2014-08-27T16:33:39.215Z",
                                  "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host':
                'testserver',
                'context': {
                    'user_id':
                    SEGMENTIO_TEST_USER_ID,
                    'course_id':
                    course_id,
                    'org_id':
                    'foo',
                    'path':
                    SEGMENTIO_TEST_ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'application': {
                        'name': 'edx.mobileapp.android',
                        'version': '29',
                        'component': 'videoplayer'
                    },
                    'received_at':
                    datetime.strptime("2014-08-27T16:33:39.100Z",
                                      "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
                'event': {
                    'currentTime': 132.134456,
                    'id': 'i4x-foo-bar-baz-some_module',
                    'code': 'mobile'
                }
            }
            if name == 'edx.video.loaded':
                # We use the same expected payload for all of these types of events, but the load video event is the
                # only one that is not actually expected to contain a "current time" field. So we remove it from the
                # expected event here.
                del expected_event['event']['currentTime']
        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event, actual_event)
Esempio n. 30
0
    def test_previous_builds(
        self,
        requested_skip_interval,
        expected_skip_interval,
        seek_type_key,
        seek_type,
        expected_seek_type,
        name,
        expected_name,
        platform,
        version,
    ):
        """
        Test backwards compatibility of previous app builds

        iOS version 1.0.02: Incorrectly emits the skip back 30 seconds as +30
        instead of -30.
        Android version 1.0.02: Skip and slide were both being returned as a
        skip. Skip or slide is determined by checking if the skip time is == -30
        Additionally, for both of the above mentioned versions, edx.video.seeked
        was sent instead of edx.video.position.changed
        """
        course_id = 'foo/bar/baz'
        middleware = TrackMiddleware()
        input_payload = {
            "code": "mobile",
            "new_time": 89.699177437,
            "old_time": 119.699177437,
            seek_type_key: seek_type,
            "requested_skip_interval": requested_skip_interval,
            'module_id': 'i4x://foo/bar/baz/some_module',
        }
        request = self.create_request(data=self.create_segmentio_event_json(
            name=name,
            data=input_payload,
            context={
                'open_in_browser_url':
                'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity/2',
                'course_id': course_id,
                'application': {
                    'name': platform,
                    'version': version,
                    'component': 'videoplayer'
                }
            },
        ),
                                      content_type='application/json')
        User.objects.create(pk=SEGMENTIO_TEST_USER_ID,
                            username=str(sentinel.username))

        middleware.process_request(request)
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'accept_language':
                '',
                'referer':
                '',
                'username':
                str(sentinel.username),
                'ip':
                '',
                'session':
                '',
                'event_source':
                'mobile',
                'event_type':
                "seek_video",
                'name':
                expected_name,
                'agent':
                str(sentinel.user_agent),
                'page':
                'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity',
                'time':
                datetime.strptime("2014-08-27T16:33:39.215Z",
                                  "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host':
                'testserver',
                'context': {
                    'user_id':
                    SEGMENTIO_TEST_USER_ID,
                    'course_id':
                    course_id,
                    'org_id':
                    'foo',
                    'path':
                    SEGMENTIO_TEST_ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'application': {
                        'name': platform,
                        'version': version,
                        'component': 'videoplayer'
                    },
                    'received_at':
                    datetime.strptime("2014-08-27T16:33:39.100Z",
                                      "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
                'event': {
                    "code": "mobile",
                    "new_time": 89.699177437,
                    "old_time": 119.699177437,
                    "type": expected_seek_type,
                    "requested_skip_interval": expected_skip_interval,
                    'id': 'i4x-foo-bar-baz-some_module',
                }
            }
        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event, actual_event)
Esempio n. 31
0
    def test_video_event(self, name, event_type):
        course_id = 'foo/bar/baz'
        middleware = TrackMiddleware()

        input_payload = {
            'current_time': 132.134456,
            'module_id': 'i4x://foo/bar/baz/some_module',
            'code': 'mobile'
        }
        if name == 'edx.video.loaded':
            del input_payload['current_time']

        request = self.create_request(data=self.create_segmentio_event_json(
            name=name,
            data=input_payload,
            context={
                'open_in_browser_url':
                'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity/2',
                'course_id': course_id,
                'application': {
                    'name': 'edx.mobileapp.android',
                    'version': '29',
                    'component': 'videoplayer'
                }
            }),
                                      content_type='application/json')
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event_without_payload = {
                'username':
                str(sentinel.username),
                'ip':
                '',
                'session':
                '',
                'event_source':
                'mobile',
                'event_type':
                event_type,
                'name':
                name,
                'agent':
                str(sentinel.user_agent),
                'page':
                'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity',
                'time':
                datetime.strptime("2014-08-27T16:33:39.215Z",
                                  "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host':
                'testserver',
                'context': {
                    'user_id':
                    USER_ID,
                    'course_id':
                    course_id,
                    'org_id':
                    'foo',
                    'path':
                    ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'application': {
                        'name': 'edx.mobileapp.android',
                        'version': '29',
                        'component': 'videoplayer'
                    },
                    'received_at':
                    datetime.strptime("2014-08-27T16:33:39.100Z",
                                      "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
            }
            expected_payload = {
                'currentTime': 132.134456,
                'id': 'i4x-foo-bar-baz-some_module',
                'code': 'mobile'
            }
            if name == 'edx.video.loaded':
                del expected_payload['currentTime']
        finally:
            middleware.process_response(request, None)

        actual_event = dict(self.get_event())
        payload = json.loads(actual_event.pop('event'))

        self.assertEquals(actual_event, expected_event_without_payload)
        self.assertEquals(payload, expected_payload)
Esempio n. 32
0
class TrackMiddlewareTestCase(TestCase):

    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_request_in_course_context(self):
        request = self.request_factory.get('/courses/test_org/test_course/test_run/foo')
        self.track_middleware.process_request(request)
        captured_context = tracker.get_tracker().resolve_context()
        self.track_middleware.process_response(request, None)

        self.assertEquals(
            captured_context,
            {
                'course_id': 'test_org/test_course/test_run',
                'org_id': 'test_org',
                'user_id': ''
            }
        )
        self.assertEquals(
            tracker.get_tracker().resolve_context(),
            {}
        )

    def test_request_with_user(self):
        request = self.request_factory.get('/courses/')
        request.user = User(pk=1)
        self.track_middleware.process_request(request)
        self.addCleanup(self.track_middleware.process_response, request, None)
        self.assertEquals(
            tracker.get_tracker().resolve_context(),
            {
                'course_id': '',
                'org_id': '',
                'user_id': 1
            }
        )
Esempio n. 33
0
    def test_previous_builds(self,
                             requested_skip_interval,
                             expected_skip_interval,
                             seek_type_key,
                             seek_type,
                             expected_seek_type,
                             name,
                             expected_name,
                             platform,
                             version,
                             ):
        """
        Test backwards compatibility of previous app builds

        iOS version 1.0.02: Incorrectly emits the skip back 30 seconds as +30
        instead of -30.
        Android version 1.0.02: Skip and slide were both being returned as a
        skip. Skip or slide is determined by checking if the skip time is == -30
        Additionally, for both of the above mentioned versions, edx.video.seeked
        was sent instead of edx.video.position.changed
        """
        course_id = 'foo/bar/baz'
        middleware = TrackMiddleware()
        input_payload = {
            "code": "mobile",
            "new_time": 89.699177437,
            "old_time": 119.699177437,
            seek_type_key: seek_type,
            "requested_skip_interval": requested_skip_interval,
            'module_id': 'i4x://foo/bar/baz/some_module',
        }
        request = self.create_request(
            data=self.create_segmentio_event_json(
                name=name,
                data=input_payload,
                context={
                    'open_in_browser_url': 'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity/2',
                    'course_id': course_id,
                    'application': {
                        'name': platform,
                        'version': version,
                        'component': 'videoplayer'
                    }
                },
            ),
            content_type='application/json'
        )
        User.objects.create(pk=USER_ID, username=str(sentinel.username))

        middleware.process_request(request)
        try:
            response = segmentio.segmentio_event(request)
            self.assertEquals(response.status_code, 200)

            expected_event = {
                'accept_language': '',
                'referer': '',
                'username': str(sentinel.username),
                'ip': '',
                'session': '',
                'event_source': 'mobile',
                'event_type': "seek_video",
                'name': expected_name,
                'agent': str(sentinel.user_agent),
                'page': 'https://testserver/courses/foo/bar/baz/courseware/Week_1/Activity',
                'time': datetime.strptime("2014-08-27T16:33:39.215Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                'host': 'testserver',
                'context': {
                    'user_id': USER_ID,
                    'course_id': course_id,
                    'org_id': 'foo',
                    'path': ENDPOINT,
                    'client': {
                        'library': {
                            'name': 'test-app',
                            'version': 'unknown'
                        },
                        'app': {
                            'version': '1.0.1',
                        },
                    },
                    'application': {
                        'name': platform,
                        'version': version,
                        'component': 'videoplayer'
                    },
                    'received_at': datetime.strptime("2014-08-27T16:33:39.100Z", "%Y-%m-%dT%H:%M:%S.%fZ"),
                },
                'event': {
                    "code": "mobile",
                    "new_time": 89.699177437,
                    "old_time": 119.699177437,
                    "type": expected_seek_type,
                    "requested_skip_interval": expected_skip_interval,
                    'id': 'i4x-foo-bar-baz-some_module',
                }
            }
        finally:
            middleware.process_response(request, None)

        actual_event = self.get_event()
        assert_event_matches(expected_event, actual_event)
Esempio n. 34
0
class TrackMiddlewareTestCase(TestCase):
    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path('/courses/')
        self.assertEquals(
            context, {
                'user_id': '',
                'session': '',
                'username': '',
                'ip': '127.0.0.1',
                'host': 'testserver',
                'agent': '',
                'path': '/courses/',
                'org_id': '',
                'course_id': '',
            })

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(tracker.get_tracker().resolve_context(), {})

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path(
            '/courses/test_org/test_course/test_run/foo')
        expected_context_subset = {
            'course_id': 'test_org/test_course/test_run',
            'org_id': 'test_org',
        }
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get('/courses/')
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'user_id': user_id,
            'username': username,
        })

    def test_request_with_session(self):
        request = self.request_factory.get('/courses/')
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'session': session_key,
        })

    def test_request_headers(self):
        ip_address = '10.0.0.0'
        user_agent = 'UnitTest/1.0'

        factory = RequestFactory(REMOTE_ADDR=ip_address,
                                 HTTP_USER_AGENT=user_agent)
        request = factory.get('/some-path')
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {
            'ip': ip_address,
            'agent': user_agent,
        })
Esempio n. 35
0
 def setUp(self):
     self.track_middleware = TrackMiddleware()
     self.request_factory = RequestFactory()
Esempio n. 36
0
class TrackMiddlewareTestCase(TestCase):
    """  Class for checking tracking requests """
    def setUp(self):
        super(TrackMiddlewareTestCase, self).setUp()
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

        patcher = patch('track.views.server_track')
        self.mock_server_track = patcher.start()
        self.addCleanup(patcher.stop)

    def test_normal_request(self):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @ddt.unpack
    @ddt.data(
        ('HTTP_USER_AGENT', 'agent'),
        ('PATH_INFO', 'path'),
        ('HTTP_REFERER', 'referer'),
        ('HTTP_ACCEPT_LANGUAGE', 'accept_language'),
    )
    def test_request_with_latin1_characters(self, meta_key, context_key):
        """
        When HTTP headers contains latin1 characters.
        """
        request = self.request_factory.get('/somewhere')
        # pylint: disable=no-member
        request.META[meta_key] = 'test latin1 \xd3 \xe9 \xf1'  # pylint: disable=no-member

        context = self.get_context_for_request(request)
        # The bytes in the string on the right are utf8 encoded in the source file, so we decode them to construct
        # a valid unicode string.
        self.assertEqual(context[context_key],
                         'test latin1 Ó é ñ'.decode('utf8'))

    def test_default_filters_do_not_render_view(self):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(self.mock_server_track.called)
            self.mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(self.mock_server_track.called)
        self.mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(self.mock_server_track.called)

    def test_default_request_context(self):
        context = self.get_context_for_path('/courses/')
        self.assertEquals(
            context, {
                'accept_language': '',
                'referer': '',
                'user_id': '',
                'session': '',
                'username': '',
                'ip': '127.0.0.1',
                'host': 'testserver',
                'agent': '',
                'path': '/courses/',
                'org_id': '',
                'course_id': '',
                'client_id': None,
            })

    def test_no_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'

        request.META['REMOTE_ADDR'] = remote_addr
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], remote_addr)

    def test_single_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'
        forwarded_ip = '11.22.33.44'

        request.META['REMOTE_ADDR'] = remote_addr
        request.META['HTTP_X_FORWARDED_FOR'] = forwarded_ip
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], forwarded_ip)

    def test_multiple_forward_for_header_ip_context(self):
        request = self.request_factory.get('/courses/')
        remote_addr = '127.0.0.1'
        forwarded_ip = '11.22.33.44, 10.0.0.1, 127.0.0.1'

        request.META['REMOTE_ADDR'] = remote_addr
        request.META['HTTP_X_FORWARDED_FOR'] = forwarded_ip
        context = self.get_context_for_request(request)

        self.assertEquals(context['ip'], '11.22.33.44')

    def get_context_for_path(self, path):
        """Extract the generated event tracking context for a given request for the given path."""
        request = self.request_factory.get(path)
        return self.get_context_for_request(request)

    def get_context_for_request(self, request):
        """Extract the generated event tracking context for the given request."""
        self.track_middleware.process_request(request)
        try:
            captured_context = tracker.get_tracker().resolve_context()
        finally:
            self.track_middleware.process_response(request, None)

        self.assertEquals(tracker.get_tracker().resolve_context(), {})

        return captured_context

    def test_request_in_course_context(self):
        captured_context = self.get_context_for_path(
            '/courses/test_org/test_course/test_run/foo')
        expected_context_subset = {
            'course_id': 'test_org/test_course/test_run',
            'org_id': 'test_org',
        }
        self.assert_dict_subset(captured_context, expected_context_subset)

    def assert_dict_subset(self, superset, subset):
        """Assert that the superset dict contains all of the key-value pairs found in the subset dict."""
        for key, expected_value in subset.iteritems():
            self.assertEquals(superset[key], expected_value)

    def test_request_with_user(self):
        user_id = 1
        username = sentinel.username

        request = self.request_factory.get('/courses/')
        request.user = User(pk=user_id, username=username)

        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'user_id': user_id,
            'username': username,
        })

    def test_request_with_session(self):
        request = self.request_factory.get('/courses/')
        SessionMiddleware().process_request(request)
        request.session.save()
        session_key = request.session.session_key
        expected_session_key = self.track_middleware.encrypt_session_key(
            session_key)
        self.assertEquals(len(session_key), len(expected_session_key))
        context = self.get_context_for_request(request)
        self.assert_dict_subset(context, {
            'session': expected_session_key,
        })

    @override_settings(SECRET_KEY='85920908f28904ed733fe576320db18cabd7b6cd')
    def test_session_key_encryption(self):
        session_key = '665924b49a93e22b46ee9365abf28c2a'
        expected_session_key = '3b81f559d14130180065d635a4f35dd2'
        encrypted_session_key = self.track_middleware.encrypt_session_key(
            session_key)
        self.assertEquals(encrypted_session_key, expected_session_key)

    def test_request_headers(self):
        ip_address = '10.0.0.0'
        user_agent = 'UnitTest/1.0'
        client_id_header = '123.123'

        factory = RequestFactory(REMOTE_ADDR=ip_address,
                                 HTTP_USER_AGENT=user_agent,
                                 HTTP_X_EDX_GA_CLIENT_ID=client_id_header)
        request = factory.get('/some-path')
        context = self.get_context_for_request(request)

        self.assert_dict_subset(context, {
            'ip': ip_address,
            'agent': user_agent,
            'client_id': client_id_header
        })

    @patch('track.middleware.TRUNCATION_LENGTH', 6)
    def test_student_answer_request(self):
        request = self.request_factory.post('/dummy')
        request.POST = {'student_answer': ['firstanswer', 'secondanswer']}
        self.track_middleware.process_request(request)
        event = '{"POST": {"student_answer": ["fir", "sec"]}, "GET": {}}'
        self.mock_server_track.assert_called_with(request,
                                                  request.META['PATH_INFO'],
                                                  event)

    @patch('track.middleware.TRUNCATION_LENGTH', 20)
    def test_submission_request(self):
        request = self.request_factory.post('/dummy')
        request.POST = {
            '{"submission":["first open response", "second open response"]}':
            []
        }
        self.track_middleware.process_request(request)
        event = '{"POST": {"submission": ["first open", "second ope"]}, "GET": {}}'
        self.mock_server_track.assert_called_with(request,
                                                  request.META['PATH_INFO'],
                                                  event)