Exemple #1
0
    def test_add_valid_action(self):
        Log.objects().delete()
        body = [{
            'userId':
            '1234',
            'sessionId':
            '12345',
            'actions': [{
                "time": "2018-10-20T21:37:28-06:00",
                "type": "VIEW",
                "properties": {
                    "viewedId": "12345"
                }
            }]
        }]
        action = Action(_type="VIEW",
                        _properties=ViewProperties(viewedId="12345"),
                        _time="2018-10-20T21:37:28-06:00")
        result = LogService.add_logs(body)

        logs = Log.objects(userId="1234")
        assert logs is not None
        assert len(logs) == 1
        assert logs[0].userId == "1234"
        assert logs[0].sessionId == "12345"
        assert logs[0].actions == [action]
        Log.objects().delete()
 def test_status_code_with_valid_get_request(self):
     Log.objects().delete()
     r = self.w.get('/logs/?')
     # Assert there was no messages flushed:
     assert r is not None
     assert r.content_type == 'application/json'
     assert r.status_int < 400
Exemple #3
0
 def test_add_no_log(self):
     Log.objects().delete()
     try:
         result = LogService.add_logs(None)
         assert False
     except Exception as e:
         assert str(e) == "NO_LOGS_PROVIDED"
 def test_retrieving_with_invalid_to_date(self):
     Log.objects().delete()
     r = self.w.get('/logs/?to=2018-10-18T21:37:28-04:00',
                    expect_errors=True)
     # Assert there was no messages flushed:
     assert r.status_int == 400
     assert r.json == {'code': 'INVALID_TIME_FORMAT', 'success': False}
    def test_empty_actions(self):
        Log.objects().delete()
        body = [{'userId': '12345', 'sessionId': '1234', 'actions': []}]

        r1 = self.w.post_json('/logs/', body, expect_errors=True)
        assert r1.status_int == 400
        assert r1.json == {'success': False, 'code': 'MISSING_ACTIONS'}
Exemple #6
0
    def add_logs(self, logs):
        if not logs: raise ValueError('NO_LOGS_PROVIDED')
        
        # Run through all received logs. This for-loop does two things
        # - Validates all inputs
        # - Once all is validated, returns an array of actions well constructed by our helper below.
        #
        # This way if any log in the body is invalid, then the entire body doesn't get inserted. Simulating a rollback.
        #

        logArray = []

        for log in logs:
            userId = log.get('userId')
            sessionId = log.get('sessionId')
            actions = log.get('actions')
            
            if not userId: raise ValueError('MISSING_USERID')
            if not sessionId: raise ValueError('MISSING_SESSIONID')
            if not actions: raise ValueError('MISSING_ACTIONS')

            actionArray = []
            
            for action in actions:
                actionArray.append(self._createActionModel(action))
            logArray.append({ 'userId': userId, 'sessionId': sessionId, 'actionArray': actionArray})

        # Validation and creation of array objects complete. Insert them all into Log collections
        for _log in logArray:
            Log.objects(
                userId=_log.get('userId'), 
                sessionId=_log.get('sessionId')
            ).update_one(push_all__actions=_log.get('actionArray'), upsert=True)
        
        return { 'success': True }
Exemple #7
0
 def test_invalid_datetime_format_logs_3(self):
     Log.objects().delete()
     try:
         result = LogService.get_logs(None, '2018-10-20T21:37:28-04:00',
                                      '2018-10-20T21:37:28-04:00', None)
         assert False
     except Exception as e:
         assert str(e) == "INVALID_TIME_FORMAT"
Exemple #8
0
 def test_miss_action(self):
     Log.objects().delete()
     try:
         body = [{'userId': '12345', 'sessionId': '12345', 'actions': []}]
         result = LogService.add_logs(body)
         assert False
     except ValueError as e:
         assert str(e) == "MISSING_ACTIONS"
Exemple #9
0
    def test_db_doesnt_add_body_if_any_log_is_invalid(self):
        Log.objects().delete()

        body = [{
            "userId":
            "ABC123XYZ",
            "sessionId":
            "XYZ456ABC",
            "actions": [{
                "time": "2018-10-18T21:37:28-06:00",
                "type": "CLICK",
                "properties": {
                    "locationX": 52,
                    "locationY": 11
                }
            }, {
                "time": "2018-10-18T21:37:30-06:00",
                "type": "VIEW",
                "properties": {
                    "viewedId": "FDJKLHSLD"
                }
            }, {
                "time": "2018-10-18T21:37:30-06:00",
                "type": "NAVIGATE",
                "properties": {
                    "pageFrom": "communities",
                    "pageTo": "inventory"
                }
            }]
        }, {
            "userId":
            "asd",
            "sessionId":
            "asdfg",
            "actions": [{
                "time": "2018-10-18T21:37:28-06:00",
                "type": "CLICK",
                "properties": {
                    "locationX": 60,
                    "locationY": 70
                }
            }, {
                "time": "2018-10-20T21:37:28-06:00",
                "type": "NAVIGATE",
                "properties": {
                    "viewedId": "1234",
                }
            }]
        }]
        try:
            result = LogService.add_logs(body)
            False
        except Exception as e:
            assert str(e) == "MISSING_PAGEFROM_VALUE"
            log = Log.objects()
            assert log is not None
            assert len(log) == 0
    def test_retrieving_valid_log(self):
        Log.objects().delete()
        answer = [{
            'userId':
            '12345',
            'sessionId':
            'asdfg',
            'actions': [{
                'type': 'CLICK',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                },
                'time': '2018-10-18T21:37:28-06:00'
            }]
        }]
        action = Action(_time='2018-10-18T21:37:28-06:00',
                        _type='CLICK',
                        _properties=ClickProperties(locationX=52,
                                                    locationY=22))
        log = Log(userId='12345', sessionId='asdfg', actions=[action])
        log.save()

        r = self.w.get('/logs/?')
        log.delete()
        assert r.json == answer
    def test_retrieving_with_invalid_type(self):
        Log.objects().delete()
        answer = [{
            'userId':
            '12345',
            'sessionId':
            'asdfg',
            'actions': [{
                'type': 'CLICK',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                },
                'time': '2018-10-17T21:37:28-06:00'
            }]
        }]
        action1 = Action(_time='2018-10-17T21:37:28-06:00',
                         _type='CLICK',
                         _properties=ClickProperties(locationX=52,
                                                     locationY=22))
        action2 = Action(_time='2018-10-19T21:37:28-06:00',
                         _type='NAVIGATE',
                         _properties=NavigateProperties(pageFrom='X',
                                                        pageTo='Y'))
        log = Log(userId='12345',
                  sessionId='asdfg',
                  actions=[action1, action2])
        log.save()

        r1 = self.w.get('/logs/?types=CLICK,WRONGTYPE,VIEW')
        assert r1.status_int == 200
        assert r1.json == answer
        log.delete()
Exemple #12
0
    def test_logs_with_an_existing_log(self):
        Log.objects().delete()
        answer = [{
            'userId':
            '12345',
            'sessionId':
            'asdfg',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'CLICK',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                }
            }]
        }]
        action = Action(_time='2018-10-18T21:37:28-06:00',
                        _type='CLICK',
                        _properties=ClickProperties(locationX=52,
                                                    locationY=22))
        log = Log(userId='12345', sessionId='asdfg', actions=[action])
        log.save()

        result = LogService.get_logs(None, None, None, None)
        assert result is not None
        assert result == answer
        log.delete()
Exemple #13
0
    def test_add_valid_action_non_upserted_different_session(self):
        Log.objects().delete()
        body = [{
            'userId':
            '1234',
            'sessionId':
            '12345',
            'actions': [{
                "time": "2018-10-20T21:37:28-06:00",
                "type": "VIEW",
                "properties": {
                    "viewedId": "12345"
                }
            }]
        }, {
            'userId':
            '1234',
            'sessionId':
            'ASDF',
            'actions': [{
                "time": "2018-10-20T21:37:28-06:00",
                "type": "NAVIGATE",
                "properties": {
                    "pageFrom": "X",
                    "pageTo": "Y"
                }
            }]
        }]
        action1 = Action(_type="VIEW",
                         _properties=ViewProperties(viewedId="12345"),
                         _time="2018-10-20T21:37:28-06:00")
        action2 = Action(_type="NAVIGATE",
                         _properties=NavigateProperties(pageFrom="X",
                                                        pageTo="Y"),
                         _time="2018-10-20T21:37:28-06:00")
        result = LogService.add_logs(body)

        logs = Log.objects()
        assert logs is not None
        assert len(logs) == 2
        assert logs[0].userId == "1234"
        assert logs[0].sessionId == "12345"
        assert logs[0].actions == [action1]

        assert logs[1].userId == "1234"
        assert logs[1].sessionId == "ASDF"
        assert logs[1].actions == [action2]
        Log.objects().delete()
    def test_missing_time(self):
        Log.objects().delete()
        body = [{
            'userId': '12345',
            'sessionId': '1234',
            'actions': [{
                'type': 'VIEW',
                'properties': {
                    'asdf': 'asdf'
                }
            }]
        }]

        r = self.w.post_json('/logs/', body, expect_errors=True)
        assert r.status_int == 400
        assert r.json == {'success': False, 'code': 'MISSING_TIME_VALUE'}
Exemple #15
0
 def test_miss_properties(self):
     Log.objects().delete()
     try:
         body = [{
             'userId':
             '12345',
             'sessionId':
             '12345',
             'actions': [{
                 "time": "2018-10-20T21:37:28-06:00",
                 "type": "VIEW"
             }]
         }]
         result = LogService.add_logs(body)
         assert False
     except ValueError as e:
         assert str(e) == "MISSING_PROPERTIES_VALUE"
    def test_no_sessionId(self):
        Log.objects().delete()
        body = [{
            'userId':
            '12345',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'CLICK',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                }
            }]
        }]

        r1 = self.w.post_json('/logs/', body, expect_errors=True)
        assert r1.status_int == 400
        assert r1.json == {'success': False, 'code': 'MISSING_SESSIONID'}
Exemple #17
0
 def test_miss_sessionId(self):
     Log.objects().delete()
     try:
         body = [{
             'userId':
             '12345',
             'actions': [{
                 "time": "2018-10-20T21:37:28-06:00",
                 "type": "VIEW",
                 "properties": {
                     "viewedId": "12345"
                 }
             }]
         }]
         result = LogService.add_logs(body)
         assert False
     except ValueError as e:
         assert str(e) == "MISSING_SESSIONID"
Exemple #18
0
 def test_result_success(self):
     Log.objects().delete()
     body = [{
         'userId':
         '12345',
         'sessionId':
         '12345',
         'actions': [{
             "time": "2018-10-20T21:37:28-06:00",
             "type": "VIEW",
             "properties": {
                 "viewedId": "12345"
             }
         }]
     }]
     result = LogService.add_logs(body)
     assert result is not None
     assert result.get('success') is True
     Log.objects().delete()
Exemple #19
0
 def test_miss_time(self):
     Log.objects().delete()
     try:
         body = [{
             'userId':
             '12345',
             'sessionId':
             '12345',
             'actions': [{
                 "type": "VIEW",
                 "properties": {
                     "viewedId": "12345"
                 }
             }]
         }]
         result = LogService.add_logs(body)
         assert False
     except ValueError as e:
         assert str(e) == "MISSING_TIME_VALUE"
    def test_invalid_click(self):
        Log.objects().delete()
        body = [{
            'userId':
            '12345',
            'sessionId':
            '1234',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'VIEW',
                'properties': {
                    'asdf': 'asdf'
                }
            }]
        }]

        r = self.w.post_json('/logs/', body, expect_errors=True)
        assert r.status_int == 400
        assert r.json == {'success': False, 'code': 'MISSING_VIEWEDID_VALUE'}
    def test_invalid_click(self):
        Log.objects().delete()
        body1 = [{
            'userId':
            '12345',
            'sessionId':
            '1234',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'CLICK',
                'properties': {
                    'locationX': 22
                }
            }]
        }]
        body2 = [{
            'userId':
            '12345',
            'sessionId':
            '1234',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'CLICK',
                'properties': {
                    'locationY': 23
                }
            }]
        }]

        r1 = self.w.post_json('/logs/', body1, expect_errors=True)
        assert r1.status_int == 400
        assert r1.json == {
            'success': False,
            'code': 'MISSING_LOCATION_Y_VALUE'
        }

        r2 = self.w.post_json('/logs/', body2, expect_errors=True)
        assert r2.status_int == 400
        assert r2.json == {
            'success': False,
            'code': 'MISSING_LOCATION_X_VALUE'
        }
    def test_invalid_type(self):
        Log.objects().delete()
        body = [{
            'userId':
            '12345',
            'sessionId':
            '1234',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'INVALID',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                }
            }]
        }]

        r1 = self.w.post_json('/logs/', body, expect_errors=True)
        assert r1.status_int == 400
        assert r1.json == {'success': False, 'code': 'INVALID_ACTION_TYPE'}
    def test_invalid_navigate(self):
        Log.objects().delete()
        body1 = [{
            'userId':
            '12345',
            'sessionId':
            '1234',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'NAVIGATE',
                'properties': {
                    'pageTo': '22'
                }
            }]
        }]
        body2 = [{
            'userId':
            '12345',
            'sessionId':
            '1234',
            'actions': [{
                'time': '2018-10-18T21:37:28-06:00',
                'type': 'NAVIGATE',
                'properties': {
                    'pageFrom': '22'
                }
            }]
        }]

        r1 = self.w.post_json('/logs/', body1, expect_errors=True)
        assert r1.status_int == 400
        assert r1.json == {'success': False, 'code': 'MISSING_PAGEFROM_VALUE'}

        r2 = self.w.post_json('/logs/', body2, expect_errors=True)
        assert r2.status_int == 400
        assert r2.json == {'success': False, 'code': 'MISSING_PAGETO_VALUE'}
Exemple #24
0
    def test_logs_with_an_matching_log_userId(self):
        Log.objects().delete()
        answer = [{
            "userId":
            "12345",
            "sessionId":
            "asdfg",
            "actions": [{
                "time": "2018-10-18T21:37:28-06:00",
                "properties": {
                    "locationX": 52,
                    "locationY": 22
                },
                "type": "CLICK",
            }, {
                "time": "2018-10-20T21:37:28-06:00",
                "properties": {
                    "pageFrom": "X",
                    "pageTo": "Y"
                },
                "type": "NAVIGATE"
            }]
        }]
        action1 = Action(_time='2018-10-18T21:37:28-06:00',
                         _type='CLICK',
                         _properties=ClickProperties(locationX=52,
                                                     locationY=22))
        action2 = Action(_time='2018-10-20T21:37:28-06:00',
                         _type='NAVIGATE',
                         _properties=NavigateProperties(pageFrom='X',
                                                        pageTo='Y'))
        log = Log(userId='12345',
                  sessionId='asdfg',
                  actions=[action1, action2])
        log.save()

        result1 = LogService.get_logs('12345', None, None, None)
        assert result1 is not None
        assert result1 == answer
        result2 = LogService.get_logs('asdf', None, None, None)
        assert result2 is not None
        assert len(result2) == 0
        log.delete()
 def test_no_body(self):
     Log.objects().delete()
     r1 = self.w.post_json('/logs/', None, expect_errors=True)
     assert r1.status_int == 400
     assert r1.json == {'success': False, 'code': 'NO_LOGS_PROVIDED'}
    def add_valid_log(self):
        Log.objects().delete()
        body = [{
            "userId":
            "ABC123XYZ",
            "sessionId":
            "XYZ456ABC",
            "actions": [{
                "time": "2018-10-18T21:37:28-06:00",
                "type": "CLICK",
                "properties": {
                    "locationX": 52,
                    "locationY": 11
                }
            }, {
                "time": "2018-10-18T21:37:30-06:00",
                "type": "VIEW",
                "properties": {
                    "viewedId": "FDJKLHSLD"
                }
            }, {
                "time": "2018-10-18T21:37:30-06:00",
                "type": "NAVIGATE",
                "properties": {
                    "pageFrom": "communities",
                    "pageTo": "inventory"
                }
            }]
        }, {
            "userId":
            "asd",
            "sessionId":
            "asdfg",
            "actions": [{
                "time": "2018-10-18T21:37:28-06:00",
                "type": "CLICK",
                "properties": {
                    "locationX": 60,
                    "locationY": 70
                }
            }, {
                "time": "2018-10-20T21:37:28-06:00",
                "type": "NAVIGATE",
                "properties": {
                    "pageFrom": "X",
                    "pageTo": "Y"
                }
            }]
        }]

        r = self.w.post_json('/logs/', body, expect_errors=True)
        assert r.status_int == 200
        assert r.json == {'success': True}

        log = Log.objects()

        assert log is not None
        assert len(log) == 2
        assert log[0].get('userId') == 'ABC123XYZ'
        assert log[0].get('sessionId') == 'XYZ456ABC'
        actions = log[0].get('actions')
        assert actions is not None
        assert len(actions) == 3
        assert actions[0] == Action(_time="2018-10-18T21:37:28-06:00",
                                    _type="CLICK",
                                    _properties=ClickProperties(locationX=52,
                                                                locationY=11))
        assert actions[1] == Action(
            _time="2018-10-18T21:37:30-06:00",
            _type="VIEW",
            _properties=ViewProperties(viewedId="FDJKLHSLD"))
        assert actions[2] == Action(_time="2018-10-18T21:37:30-06:00",
                                    _type="NAVIGATE",
                                    _properties=NavigateProperties(
                                        pageFrom="communities",
                                        pageTo="inventory"))
        Log.objects().delete()

        assert log[1].get('userId') == 'asd'
        assert log[1].get('sessionId') == 'asdfg'
        actions = log[1].get('actions')
        assert actions is not None
        assert len(actions) == 2
        assert actions[0] == Action(_time="2018-10-18T21:37:28-06:00",
                                    _type="CLICK",
                                    _properties=ClickProperties(locationX=60,
                                                                locationY=70))
        assert actions[1] == Action(_time="2018-10-20T21:37:28-06:00",
                                    _type="NAVIGATE",
                                    _properties=NavigateProperties(
                                        pageFrom="X", pageTo="Y"))
        Log.objects().delete()
Exemple #27
0
 def test_empty_logs(self):
     Log.objects().delete()
     result = LogService.get_logs(None, None, None, None)
     assert len(result) == 0
Exemple #28
0
    def test_logs_with_a_from_and_to(self):
        Log.objects().delete()
        answer1 = [
            {
                "userId":
                "12345",
                "sessionId":
                "asdfg",
                "actions": [{
                    "time": "2018-10-17T21:37:28-06:00",
                    "properties": {
                        "locationX": 52,
                        "locationY": 22
                    },
                    "type": "CLICK"
                }]
            },
            {
                "userId":
                "ASDFG",
                "sessionId":
                "12345",
                "actions": [{
                    "time": "2018-10-18T21:37:28-06:00",
                    "properties": {
                        "viewedId": "12345"
                    },
                    "type": "VIEW"
                }]
            },
        ]

        answer2 = [
            {
                "userId":
                "12345",
                "sessionId":
                "asdfg",
                "actions": [{
                    "time": "2018-10-19T21:37:28-06:00",
                    "properties": {
                        "pageFrom": 'X',
                        "pageTo": 'Y'
                    },
                    "type": "NAVIGATE"
                }]
            },
            {
                "userId":
                "ASDFG",
                "sessionId":
                "12345",
                "actions": [{
                    "time": "2018-10-20T21:37:28-06:00",
                    "properties": {
                        "locationX": 60,
                        "locationY": 30
                    },
                    "type": "CLICK"
                }]
            },
        ]
        answer3 = [{
            "userId":
            "ASDFG",
            "sessionId":
            "12345",
            "actions": [{
                "time": "2018-10-18T21:37:28-06:00",
                "properties": {
                    "viewedId": "12345",
                },
                "type": "VIEW"
            }]
        }]

        action1 = Action(_time='2018-10-17T21:37:28-06:00',
                         _type='CLICK',
                         _properties=ClickProperties(locationX=52,
                                                     locationY=22))
        action2 = Action(_time='2018-10-19T21:37:28-06:00',
                         _type='NAVIGATE',
                         _properties=NavigateProperties(pageFrom='X',
                                                        pageTo='Y'))
        log1 = Log(userId='12345',
                   sessionId='asdfg',
                   actions=[action1, action2])
        action3 = Action(_time='2018-10-18T21:37:28-06:00',
                         _type='VIEW',
                         _properties=ViewProperties(viewedId='12345'))
        action4 = Action(_time='2018-10-20T21:37:28-06:00',
                         _type='CLICK',
                         _properties=ClickProperties(locationX=60,
                                                     locationY=30))
        log2 = Log(userId='ASDFG',
                   sessionId='12345',
                   actions=[action3, action4])
        log1.save()
        log2.save()
        result1 = LogService.get_logs(None, None, '2018-10-19T00:00:00-06:00',
                                      None)
        assert result1 is not None
        assert result1 == answer1

        result2 = LogService.get_logs(None, '2018-10-19T00:00:00-06:00', None,
                                      None)
        assert result2 is not None
        assert result2 == answer2

        result3 = LogService.get_logs(None, '2018-10-18T00:00:00-06:00',
                                      '2018-10-19T00:00:00-06:00', None)
        assert result3 is not None
        assert result3 == answer3
        log1.delete()
        log2.delete()
    def test_retrieving_log_by_user(self):
        Log.objects().delete()
        answer1 = [{
            'userId':
            'ASDF',
            'sessionId':
            '123',
            'actions': [{
                'type': 'CLICK',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                },
                'time': '2018-10-18T21:37:28-06:00'
            }]
        }]
        answer2 = [{
            'userId':
            '12345',
            'sessionId':
            'asdfg',
            'actions': [{
                'type': 'CLICK',
                'properties': {
                    'locationX': 52,
                    'locationY': 22
                },
                'time': '2018-10-18T21:37:28-06:00'
            }]
        }]
        action = Action(_time='2018-10-18T21:37:28-06:00',
                        _type='CLICK',
                        _properties=ClickProperties(locationX=52,
                                                    locationY=22))
        log1 = Log(userId='12345', sessionId='asdfg', actions=[action])
        log2 = Log(userId='ASDF', sessionId='123', actions=[action])
        log1.save()
        log2.save()

        r1 = self.w.get('/logs/?userId=ASDF')
        assert r1.json == answer1
        r2 = self.w.get('/logs/?userId=12345')
        assert r2.json == answer2
        r2 = self.w.get('/logs/?userId=12')
        assert r2.json == []

        log1.delete()
        log2.delete()
    def test_retrieving_logs_with_matching_types(self):
        Log.objects().delete()
        answer1 = [
            {
                "userId":
                "12345",
                "sessionId":
                "asdfg",
                "actions": [{
                    "time": "2018-10-20T21:37:28-06:00",
                    "properties": {
                        "locationX": 52,
                        "locationY": 22
                    },
                    "type": "CLICK"
                }]
            },
            {
                "userId":
                "ASDFG",
                "sessionId":
                "12345",
                "actions": [{
                    "time": "2019-10-20T21:37:28-06:00",
                    "properties": {
                        "locationX": 60,
                        "locationY": 30
                    },
                    "type": "CLICK"
                }]
            },
        ]

        answer2 = [
            {
                "userId":
                "12345",
                "sessionId":
                "asdfg",
                "actions": [{
                    "time": "2018-10-20T21:37:28-06:00",
                    "properties": {
                        "locationX": 52,
                        "locationY": 22
                    },
                    "type": "CLICK"
                }]
            },
            {
                "userId":
                "ASDFG",
                "sessionId":
                "12345",
                "actions": [{
                    "time": "2019-10-19T21:37:28-06:00",
                    "properties": {
                        "viewedId": "12345",
                    },
                    "type": "VIEW"
                }, {
                    "time": "2019-10-20T21:37:28-06:00",
                    "properties": {
                        "locationX": 60,
                        "locationY": 30
                    },
                    "type": "CLICK"
                }]
            },
        ]
        answer3 = [{
            "userId":
            "12345",
            "sessionId":
            "asdfg",
            "actions": [{
                "time": "2018-10-20T21:37:28-06:00",
                "properties": {
                    "pageFrom": "X",
                    "pageTo": "Y"
                },
                "type": "NAVIGATE"
            }]
        }]

        action1 = Action(_time='2018-10-20T21:37:28-06:00',
                         _type='CLICK',
                         _properties=ClickProperties(locationX=52,
                                                     locationY=22))
        action2 = Action(_time='2018-10-20T21:37:28-06:00',
                         _type='NAVIGATE',
                         _properties=NavigateProperties(pageFrom='X',
                                                        pageTo='Y'))
        log1 = Log(userId='12345',
                   sessionId='asdfg',
                   actions=[action1, action2])
        action3 = Action(_time='2019-10-19T21:37:28-06:00',
                         _type='VIEW',
                         _properties=ViewProperties(viewedId='12345'))
        action4 = Action(_time='2019-10-20T21:37:28-06:00',
                         _type='CLICK',
                         _properties=ClickProperties(locationX=60,
                                                     locationY=30))
        log2 = Log(userId='ASDFG',
                   sessionId='12345',
                   actions=[action3, action4])
        log1.save()
        log2.save()

        r1 = self.w.get('/logs/?types=CLICK')
        assert r1.json == answer1
        r2 = self.w.get('/logs/?types=CLICK,VIEW')
        assert r2.json == answer2
        r3 = self.w.get('/logs/?types=NAVIGATE')
        assert r3.json == answer3
        log1.delete()
        log2.delete()