def test_ticket_cancel(self):
        """Test can cancel ticket."""
        with self.app.app_context():
            user = UserFactory()
            user.is_admin = True
            access_token = User.generate_token(user.id)
            ticket = TicketFactory.build()
            ticket.booked_by = user
            ticket.save()

            response = self.client.delete(f'/api/tickets/cancel/{ticket.id}',
                                          headers={
                                              'Authorization': access_token,
                                              'content-type':
                                              'application/json'
                                          })

            result = json.loads(response.data.decode())
            self.assertEqual(response.status_code, 200)
            self.assertEqual(result['message'],
                             'Ticket successfully cancelled.')

            with self.subTest('Ticket no longer exists'):
                response = self.client.get(f'/api/tickets/{user.id}',
                                           headers={
                                               'Authorization': access_token,
                                               'content-type':
                                               'application/json'
                                           })

                result = json.loads(response.data.decode())
                self.assertEqual(response.status_code, 200)
                self.assertEqual(len(result['tickets']), 0)
    def test_create_flight(self):
        """Test flight can be created."""
        with self.app.app_context():
            user = UserFactory()
            user.is_admin = True
            access_token = User.generate_token(user.id)

            route_1 = RouteFactory()
            route_2 = RouteFactory()
            flight = FlightFactory.build()

            response = self.client.post('/api/flights',
                                        data=json.dumps(
                                            {
                                                'origin_id': route_1.id,
                                                'destination_id': route_2.id,
                                                'departure': flight.departure,
                                                'arrival': flight.arrival,
                                                'price': flight.price,
                                                'capacity': flight.capacity
                                            },
                                            cls=JsonEncoderWithDatetime),
                                        headers={
                                            'Authorization': access_token,
                                            'content-type': 'application/json'
                                        })

        result = json.loads(response.data.decode())
        self.assertEqual(response.status_code, 201)
        self.assertEqual(result['message'], 'Flight created.')
    def test_get_all_flights_with_date_range(self):
        """Test can get all flights filtered by date range."""
        with self.app.app_context():
            user = UserFactory()
            access_token = User.generate_token(user.id)
            flight_1 = FlightFactory()

            with self.subTest('Raise an error for dates with wrong format'):
                response = self.client.get('/api/flights',
                                           query_string={
                                               'from': 'not-a-real-date',
                                               'to': 'also-not-real'
                                           },
                                           headers={
                                               'Authorization': access_token,
                                               'content-type': 'application/json'
                                           })

                result = json.loads(response.data.decode())
                self.assertEqual(response.status_code, 422)
                self.assertIn("does not match format '%Y-%m-%dT%H:%M:%S'", result['messages'])

            with self.subTest('No results for flights in the past'):
                response = self.client.get('/api/flights',
                                           query_string={
                                               'from': '2018-07-19T00:00:00',
                                               'to': '2018-07-23T00:00:00'
                                           },
                                           headers={
                                               'Authorization': access_token,
                                               'content-type': 'application/json'
                                           })

                result = json.loads(response.data.decode())
                self.assertEqual(response.status_code, 200)
                self.assertEqual(len(result['flights']), 0)

            with self.subTest('Results adhere to date range filter'):
                from_date = flight_1.departure - timedelta(days=1)
                to_date = flight_1.arrival + timedelta(days=1)

                response = self.client.get('/api/flights',
                                           query_string={
                                               'from': from_date.strftime('%Y-%m-%dT%H:%M:%S'),
                                               'to': to_date.strftime('%Y-%m-%dT%H:%M:%S')
                                           },
                                           headers={
                                               'Authorization': access_token,
                                               'content-type': 'application/json'
                                           })

                result = json.loads(response.data.decode())
                self.assertEqual(response.status_code, 200)
                self.assertGreater(len(result['flights']), 0)
    def test_photo_download(self):
        """Test user can download photo."""
        with self.app.app_context():
            photo = PhotoFactory()
            access_token = User.generate_token(photo.uploaded_by_id)

        response = self.client.get('/api/users/photo/download',
                                   headers={
                                       'Authorization': access_token,
                                   })

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data, photo.data)
    def test_get_by_destination(self):
        """Test can get flight by destination."""
        with self.app.app_context():
            user = UserFactory()
            access_token = User.generate_token(user.id)
            flight = FlightFactory()

            response = self.client.get(f'/api/flights/destination/{flight.destination_id}',
                                       headers={
                                           'Authorization': access_token,
                                           'content-type': 'application/json'
                                       })

            result = json.loads(response.data.decode())
            self.assertEqual(response.status_code, 200)
            self.assertEqual(len(result['flights']), 1)
            self.assertEqual(result['flights'][0]['origin_id'], flight.origin_id)
            self.assertEqual(result['flights'][0]['destination_id'], flight.destination_id)
    def test_get_by_user_id(self):
        """Test can get ticket by user id."""
        with self.app.app_context():
            user = UserFactory()
            user.is_admin = True
            access_token = User.generate_token(user.id)
            ticket = TicketFactory()

            response = self.client.get(f'/api/tickets/{ticket.booked_by_id}',
                                       headers={
                                           'Authorization': access_token,
                                           'content-type': 'application/json'
                                       })

            result = json.loads(response.data.decode())
            self.assertEqual(response.status_code, 200)
            self.assertEqual(len(result['tickets']), 1)
            self.assertEqual(result['tickets'][0]['flight_id'],
                             ticket.flight_id)
    def test_create_ticket(self):
        """Test ticket can be created."""
        with self.app.app_context():
            user = UserFactory()
            user.is_admin = True
            access_token = User.generate_token(user.id)

            flight = FlightFactory()

            response = self.client.post('/api/tickets/book',
                                        data=json.dumps(
                                            {'flight_id': flight.id}),
                                        headers={
                                            'Authorization': access_token,
                                            'content-type': 'application/json'
                                        })

        result = json.loads(response.data.decode())
        self.assertEqual(response.status_code, 201)
        self.assertEqual(result['message'], 'Ticket successfully booked.')
    def test_get_mine(self):
        """Test user can get own ticket details."""
        with self.app.app_context():
            user = UserFactory()
            access_token = User.generate_token(user.id)
            ticket = TicketFactory.build()
            ticket.booked_by = user
            ticket.save()

            response = self.client.get('/api/tickets/mine',
                                       headers={
                                           'Authorization': access_token,
                                           'content-type': 'application/json'
                                       })

            result = json.loads(response.data.decode())
            self.assertEqual(response.status_code, 200)
            self.assertEqual(len(result['tickets']), 1)
            self.assertEqual(result['tickets'][0]['flight_id'],
                             ticket.flight_id)
    def test_photo_upload(self):
        """Test user can upload photo."""
        with self.app.app_context():
            user = UserFactory()
            access_token = User.generate_token(user.id)

        with self.subTest('Jpgs are uploaded correctly'):
            response = self.client.post(
                '/api/users/photo/upload',
                data={'data': (io.BytesIO(b'yaddayadda'), 'test_photo.jpg')},
                headers={
                    'Authorization': access_token,
                    'content-type': 'multipart/form-data'
                })

            result = json.loads(response.data.decode())
            self.assertEqual(response.status_code, 201)
            self.assertEqual(result['message'],
                             'Photo test_photo.jpg successfully uploaded.')

            with self.app.app_context():
                photo = Photo.query.get(1)
            self.assertEqual(photo.data, b'yaddayadda')

        with self.subTest('None Jpgs are NOT uploaded'):
            response = self.client.post(
                '/api/users/photo/upload',
                data={'data': (io.BytesIO(b'yaddayadda'), 'test_photo.txt')},
                headers={
                    'Authorization': access_token,
                    'content-type': 'multipart/form-data'
                })

            result = json.loads(response.data.decode())
            self.assertEqual(response.status_code, 422)
            self.assertEqual(result['messages']['data'], ['Invalid value.'])