Ejemplo n.º 1
0
    def test_invalid_jws(self, api_client, shipment_alice_with_device):
        response = api_client.post(self.url_device,
                                   {'payload': {
                                       'this': 'is not a jws'
                                   }})
        AssertionHelper.HTTP_400(
            response, error='This value does not match the required pattern.')

        response = api_client.post(self.url_device,
                                   {'payload': 'neither.is.this'})
        AssertionHelper.HTTP_400(
            response,
            error=
            "Invalid JWS: Invalid header string: 'utf-8' codec can't decode byte 0x9d in position 0: invalid start byte"
        )

        response = api_client.post(self.url_device, {'payload': 'or.this'})
        AssertionHelper.HTTP_400(
            response, error='This value does not match the required pattern.')

        response = api_client.post(
            self.url_device,
            {'payload': 'bm9ybm9ybm9y.aXNpc2lz.dGhpc3RoaXN0aGlz'})
        AssertionHelper.HTTP_400(
            response,
            error=
            'Invalid JWS: Invalid header string: Expecting value: line 1 column 1 (char 0)'
        )
    def test_tracking_telemetry_ro(self, shipment_alice, client_bob,
                                   new_access_request_bob,
                                   access_request_rw_attributes):
        response = client_bob.patch(
            self.detail_url,
            {'tracking_permission': PermissionLevel.READ_WRITE.name})
        AssertionHelper.HTTP_400(response,
                                 'Cannot request write access to this field')

        response = client_bob.patch(
            self.detail_url,
            {'telemetry_permission': PermissionLevel.READ_WRITE.name})
        AssertionHelper.HTTP_400(response,
                                 'Cannot request write access to this field')
Ejemplo n.º 3
0
def test_create_shipment_note(user_alice, shipper_user, api_client, shipper_api_client, client_alice,
                              shipment, mocked_is_shipper, successful_wallet_owner_calls_assertions):

    url = reverse('shipment-notes-list', kwargs={'version': 'v1', 'shipment_pk': shipment.id})
    create_note_data, content_type = create_form_content({'message': MESSAGE_1})

    # An unauthenticated user cannot create a shipment note
    response = api_client.post(url, {'message': MESSAGE_1})
    AssertionHelper.HTTP_403(response, error='You do not have permission to perform this action.')

    # An authenticated request with a empty message should fail
    response = client_alice.post(url, {'message': ''})
    AssertionHelper.HTTP_400(response, error='This field may not be blank.', pointer='message')

    # An authenticated request with a message with more than 500 characters should fail
    response = client_alice.post(url, {'message': MESSAGE_2})
    AssertionHelper.HTTP_400(response,
                             error='Ensure this value has at most 500 characters (it has 632).',
                             pointer='message')

    # An authenticated user can create a shipment note
    response = client_alice.post(url, create_note_data, content_type=content_type)

    AssertionHelper.HTTP_201(response,
                             entity_refs=AssertionHelper.EntityRef(resource='ShipmentNote',
                                                                   attributes={
                                                                       'message': MESSAGE_1,
                                                                       'user_id': user_alice.id,
                                                                       'username': get_username(user_alice),
                                                                       'organization_name': get_user_org_name(
                                                                           user_alice)},
                                                                   relationships={'shipment': AssertionHelper.EntityRef(
                                                                       resource='Shipment', pk=shipment.id)})
                             )

    # A shipper also valid for moderator and carrier can add a shipment note
    response = shipper_api_client.post(url, {'message': MESSAGE_1})

    AssertionHelper.HTTP_201(response,
                             entity_refs=AssertionHelper.EntityRef(resource='ShipmentNote',
                                                                   attributes={
                                                                       'message': MESSAGE_1,
                                                                       'user_id': shipper_user.id,
                                                                       'username': get_username(shipper_user)},
                                                                   relationships={
                                                                       'shipment': AssertionHelper.EntityRef(
                                                                           resource='Shipment', pk=shipment.id)})
                             )
    mocked_is_shipper.assert_calls(successful_wallet_owner_calls_assertions)
Ejemplo n.º 4
0
def test_profiles_disabled_shipment_tag_creation(
        api_client, shipment, shipment_tag_creation_data,
        shipment_tag_creation_missing_owner_id, entity_shipment_relationship):

    url = reverse('shipment-tags-list',
                  kwargs={
                      'version': 'v1',
                      'shipment_pk': shipment.id
                  })

    # A request without user_id should fail
    response = api_client.post(url, shipment_tag_creation_missing_owner_id)
    AssertionHelper.HTTP_400(response, error='This field is required.')

    response = api_client.post(url, shipment_tag_creation_data)
    AssertionHelper.HTTP_201(
        response,
        entity_refs=AssertionHelper.EntityRef(
            resource='ShipmentTag',
            attributes={
                'tag_type': shipment_tag_creation_data['tag_type'],
                'tag_value': shipment_tag_creation_data['tag_value'],
                'owner_id': USER_ID
            },
            relationships={'shipment': entity_shipment_relationship}))
def test_pickup(client_alice, shipment):
    assert shipment.pickup_act is None
    url = reverse('shipment-actions',
                  kwargs={
                      'version': 'v1',
                      'shipment_pk': shipment.id
                  })
    action = {'action_type': ActionType.PICK_UP.name}

    response = client_alice.post(url, data=action)
    AssertionHelper.HTTP_200(
        response,
        entity_refs=AssertionHelper.EntityRef(
            resource='Shipment',
            pk=shipment.id,
            attributes={'state': TransitState.IN_TRANSIT.name}))

    updated_parameters = response.json()['data']['attributes']

    assert datetimeAlmostEqual(dt_parse(updated_parameters['pickup_act']))

    # Can't pickup when IN_TRANSIT
    response = client_alice.post(url, data=action)
    AssertionHelper.HTTP_400(
        response,
        error=
        'Action PICK_UP not available while Shipment is in state IN_TRANSIT',
        pointer='action_type')
Ejemplo n.º 6
0
def test_shipment_creation_with_assignee(client_alice, mocked_is_shipper,
                                         mocked_storage_credential, shipment):

    url = reverse('shipment-list', kwargs={'version': 'v1'})

    valid_uuid4_data = {
        'storage_credentials_id': shipment.storage_credentials_id,
        'shipper_wallet_id': shipment.shipper_wallet_id,
        'carrier_wallet_id': shipment.carrier_wallet_id,
        'assignee_id': VALID_UUID4,
    }

    invalid_uuid4_data = {
        'storage_credentials_id': shipment.storage_credentials_id,
        'shipper_wallet_id': shipment.shipper_wallet_id,
        'carrier_wallet_id': shipment.carrier_wallet_id,
        'assignee_id': VALID_UUID4[:-1],
    }

    # A shipment cannot be created with an invalid assignee ID
    response = client_alice.post(url, data=invalid_uuid4_data)
    AssertionHelper.HTTP_400(response,
                             error='Must be a valid UUID.',
                             pointer='assignee_id')

    # With a valid assignee ID the request should succeed
    response = client_alice.post(url, data=valid_uuid4_data)
    AssertionHelper.HTTP_202(response,
                             entity_refs=AssertionHelper.EntityRef(
                                 resource='Shipment',
                                 attributes={'assignee_id': VALID_UUID4}))
Ejemplo n.º 7
0
def test_shipment_update_with_assignee(client_alice, shipment):

    url = reverse('shipment-detail',
                  kwargs={
                      'version': 'v1',
                      'pk': shipment.id
                  })

    valid_uuid4_data = {
        'assignee_id': VALID_UUID4,
    }

    invalid_uuid4_data = {
        'assignee_id': VALID_UUID4 + '12',
    }

    # A shipment cannot be updated with an invalid assignee ID
    response = client_alice.patch(url, data=invalid_uuid4_data)
    AssertionHelper.HTTP_400(response,
                             error='Must be a valid UUID.',
                             pointer='assignee_id')

    # With a valid assignee ID the request should succeed
    response = client_alice.patch(url, data=valid_uuid4_data)
    AssertionHelper.HTTP_202(response,
                             entity_refs=AssertionHelper.EntityRef(
                                 resource='Shipment',
                                 pk=shipment.id,
                                 attributes={'assignee_id': VALID_UUID4}))
 def test_ro_fields(self, client_bob, user_alice_id, user_bob_id,
                    access_request_ro_attributes, current_datetime):
     response = client_bob.post(self.list_url, {
         **access_request_ro_attributes,
         **{
             'approved': True
         }
     })
     AssertionHelper.HTTP_400(
         response,
         'User does not have access to approve this access request')
     response = client_bob.post(self.list_url, {
         **access_request_ro_attributes,
         **{
             'approved_at': current_datetime
         }
     })
     AssertionHelper.HTTP_201(response, attributes={'approved_at': None})
     response = client_bob.post(self.list_url, {
         **access_request_ro_attributes,
         **{
             'approved_by': user_alice_id
         }
     })
     AssertionHelper.HTTP_201(response, attributes={'approved_by': None})
     response = client_bob.post(self.list_url, {
         **access_request_ro_attributes,
         **{
             'requester_id': user_alice_id
         }
     })
     AssertionHelper.HTTP_201(response,
                              attributes={'requester_id': user_bob_id})
Ejemplo n.º 9
0
    def test_file_types(self, client_alice, entity_ref_shipment_alice):
        attributes = {
            'name': 'Test BOL',
            'file_type': 'NOT A FILE TYPE',
            'document_type': 'BOL',
        }
        response = client_alice.post(self.shipment_alice_url, attributes)
        AssertionHelper.HTTP_400(response, error=f'"{attributes["file_type"]}" is not a valid choice.',
                                 pointer='file_type')

        attributes['file_type'] = FileType.PDF.name
        response = client_alice.post(self.shipment_alice_url, attributes)
        AssertionHelper.HTTP_201(response,
                                 entity_refs=AssertionHelper.EntityRef(
                                     resource='Document',
                                     attributes={
                                        'upload_status': UploadStatus.PENDING.name, **attributes
                                     },
                                     relationships=[{
                                         'shipment': entity_ref_shipment_alice
                                     }],
                                     meta={
                                         'presigned_s3_thumbnail': None
                                     }
                                 ))
        assert isinstance(response.json()['data']['meta']['presigned_s3'], dict)
Ejemplo n.º 10
0
    def test_timestamp(self, client_alice, unsigned_telemetry_different_hardware, current_datetime):
        telemetry_copy = deepcopy(self.unsigned_telemetry)
        telemetry_copy['timestamp'] = (current_datetime + timedelta(days=1)).isoformat().replace('+00:00', 'Z')
        add_telemetry_data_to_model([telemetry_copy], self.shipment_alice_with_device)

        valid_timestamp = (current_datetime + timedelta(hours=12)).isoformat().replace('+00:00', 'Z')
        invalid_before_timestamp = (current_datetime + timedelta(hours=18)).isoformat().replace('+00:00', 'Z')
        invalid_after_timestamp = (current_datetime + timedelta(hours=6)).isoformat().replace('+00:00', 'Z')

        response = client_alice.get(f'{self.telemetry_url}?before=NOT A TIMESTAMP')
        AssertionHelper.HTTP_400(response)
        assert response.json()['before'] == ['Enter a valid date/time.']

        response = client_alice.get(f'{self.telemetry_url}?before={valid_timestamp}')
        self.unsigned_telemetry.pop('version')
        AssertionHelper.HTTP_200(response, is_list=True, vnd=False, attributes=self.unsigned_telemetry, count=1)

        response = client_alice.get(f'{self.telemetry_url}?after={valid_timestamp}')
        telemetry_copy.pop('version')
        AssertionHelper.HTTP_200(response, is_list=True, vnd=False, attributes=telemetry_copy, count=1)

        response = client_alice.get(f'{self.telemetry_url}?before={valid_timestamp}&after={invalid_after_timestamp}')
        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert response.json()[0] == \
            f'Invalid timemismatch applied. Before timestamp {valid_timestamp} is greater than after: {invalid_after_timestamp}'

        response = client_alice.get(f'{self.telemetry_url}?after={valid_timestamp}&before={invalid_before_timestamp}')
        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert response.json()[0] == \
            f'Invalid timemismatch applied. Before timestamp {invalid_before_timestamp} is greater than after: {valid_timestamp}'
def test_arrival(client_alice, shipment):
    assert shipment.port_arrival_act is None
    url = reverse('shipment-actions',
                  kwargs={
                      'version': 'v1',
                      'shipment_pk': shipment.id
                  })
    action = {'action_type': ActionType.ARRIVAL.name}

    response = client_alice.post(url, data=action)
    AssertionHelper.HTTP_400(
        response,
        error=
        'Action ARRIVAL not available while Shipment is in state AWAITING_PICKUP',
        pointer='action_type')
    shipment.pick_up()
    shipment.save()

    response = client_alice.post(url, data=action)
    AssertionHelper.HTTP_200(
        response,
        entity_refs=AssertionHelper.EntityRef(
            resource='Shipment',
            pk=shipment.id,
            attributes={'state': TransitState.AWAITING_DELIVERY.name}))

    updated_parameters = response.json()['data']['attributes']

    assert datetimeAlmostEqual(dt_parse(
        updated_parameters['port_arrival_act']))

    # Can't pickup or arrive when AWAITING_DELIVERY
    response = client_alice.post(url, data=action)
    AssertionHelper.HTTP_400(
        response,
        error=
        'Action ARRIVAL not available while Shipment is in state AWAITING_DELIVERY',
        pointer='action_type')

    action = {'action_type': ActionType.PICK_UP.name}
    response = client_alice.post(url, data=action)
    AssertionHelper.HTTP_400(
        response,
        error=
        'Action PICK_UP not available while Shipment is in state AWAITING_DELIVERY',
        pointer='action_type')
Ejemplo n.º 12
0
    def test_route_in_progress_fails(self, client_alice, leg_attributes, shipment_on_new_route, shipment_alice):
        shipment_on_new_route.pick_up()
        shipment_on_new_route.save()

        leg_attributes['shipment_id'] = shipment_alice.pk

        response = client_alice.post(self.url_route, data=leg_attributes)
        AssertionHelper.HTTP_400(response, error='Cannot add shipment to route after transit has begun')
Ejemplo n.º 13
0
 def test_double_approval(self, client_alice, approved_access_request_bob,
                          access_request_ro_attributes):
     response = client_alice.patch(self.detail_url, {
         'approved': True,
         **access_request_ro_attributes
     })
     AssertionHelper.HTTP_400(
         response, 'This access request has already been approved')
Ejemplo n.º 14
0
    def test_shipment_in_progress_fails(self, client_alice, leg_attributes, shipment):
        shipment.pick_up()
        shipment.save()

        leg_attributes['shipment_id'] = shipment.pk

        response = client_alice.post(self.url_route, data=leg_attributes)
        AssertionHelper.HTTP_400(response, error='Shipment already picked up, cannot add to route')
Ejemplo n.º 15
0
    def test_with_device_not_authorized_fails(self, client_alice, route_attributes, device):
        route_attributes['device_id'] = device.id

        with mock.patch('apps.shipments.models.Device.get_or_create_with_permission') as mock_device:
            mock_error = 'mock unauthorized error'
            mock_device.side_effect = ValidationError(mock_error)

            response = client_alice.post(self.url, route_attributes)
            AssertionHelper.HTTP_400(response, error=mock_error)
Ejemplo n.º 16
0
 def test_permission_link_email_validation(self, client_alice):
     response = client_alice.post(
         self.url_permission_link_create, {
             'name': 'Permission Link Name',
             'emails': ['not an email', '*****@*****.**']
         })
     AssertionHelper.HTTP_400(response,
                              error='Enter a valid email address.',
                              pointer='emails')
Ejemplo n.º 17
0
    def test_required_fields(self, client_alice):
        response = client_alice.post(self.shipment_alice_url, {
            'document_type': 'Bol',
            'file_type': 'Pdf'
        })
        AssertionHelper.HTTP_400(response, error='This field is required.', pointer='name')

        response = client_alice.post(self.shipment_alice_url, {
            'name': 'Test BOL',
            'file_type': 'Pdf'
        })
        AssertionHelper.HTTP_400(response, error='This field is required.', pointer='document_type')

        response = client_alice.post(self.shipment_alice_url, {
            'name': 'Test BOL',
            'document_type': 'Bol',
        })
        AssertionHelper.HTTP_400(response, error='This field is required.', pointer='file_type')
Ejemplo n.º 18
0
 def test_tags_without_shipment(self, shipment_alice, client_bob):
     response = client_bob.patch(
         self.detail_url, {
             'shipment_permission': PermissionLevel.NONE.name,
             'tags_permission': PermissionLevel.READ_WRITE.name
         })
     AssertionHelper.HTTP_400(
         response,
         'Cannot request to view tags without shipment read access')
Ejemplo n.º 19
0
    def test_create_requires_fields(self, client_alice):
        self.base_call['tags'] = [
            {
                'tag_type': 'tag_type'
            },
        ]
        response = client_alice.post(self.url, self.base_call)
        AssertionHelper.HTTP_400(response, 'Tags items must contain `tag_value` and `tag_type`.')
        self.wallet_mocking.assert_calls(self.assertions)

        self.base_call['tags'] = [
            {
                'tag_value': 'tag_value'
            },
        ]
        response = client_alice.post(self.url, self.base_call)
        AssertionHelper.HTTP_400(response, 'Tags items must contain `tag_value` and `tag_type`.')
        self.wallet_mocking.assert_calls(self.assertions)
Ejemplo n.º 20
0
    def test_route_complete_fails(self, client_alice, shipment):
        shipment.pick_up()
        shipment.save()
        shipment.arrival()
        shipment.save()
        shipment.drop_off()
        shipment.save()

        response = client_alice.delete(self.url_route)
        AssertionHelper.HTTP_400(response, error='Cannot remove shipment from route after transit has begun')
Ejemplo n.º 21
0
def test_org_user_shipment_tag(org_id_alice, api_client, client_alice, shipment, shipment_tag_creation_data,
                               missing_tag_type_creation_data, missing_tag_value_creation_data,
                               space_in_tag_type_creation_data, space_in_tag_value_creation_data):

    url = reverse('shipment-tags-list', kwargs={'version': 'v1', 'shipment_pk': shipment.id})

    # An unauthenticated user cannot tag a shipment
    response = api_client.post(url, shipment_tag_creation_data)
    AssertionHelper.HTTP_403(response, error='You do not have permission to perform this action.')

    # An org user cannot tag a shipment with missing tag_type in creation data
    response = client_alice.post(url, missing_tag_type_creation_data)
    AssertionHelper.HTTP_400(response, error='This field is required.')

    # An org user cannot tag a shipment with missing tag_value in creation data
    response = client_alice.post(url, missing_tag_value_creation_data)
    AssertionHelper.HTTP_400(response, error='This field is required.')

    # An org user cannot tag a shipment with space in tag_value field creation data
    response = client_alice.post(url, space_in_tag_value_creation_data)
    AssertionHelper.HTTP_400(response, error='Space(s) not allowed in this field')

    # An org user cannot tag a shipment with space in tag_type field creation data
    response = client_alice.post(url, space_in_tag_type_creation_data)
    AssertionHelper.HTTP_400(response, error='Space(s) not allowed in this field')

    # An org user with proper tag data definition, should tag a shipment
    response = client_alice.post(url, shipment_tag_creation_data)
    AssertionHelper.HTTP_201(response,
                           entity_refs=AssertionHelper.EntityRef(
                               resource='ShipmentTag',
                               attributes={'tag_type': shipment_tag_creation_data['tag_type'],
                                           'tag_value': shipment_tag_creation_data['tag_value'],
                                           'owner_id': org_id_alice},
                               relationships={
                                   'shipment': AssertionHelper.EntityRef(resource='Shipment', pk=shipment.id)
                               })
                           )

    # Trying to tag a shipment with an existing (tag_type, tag_value) pair should fail
    response = client_alice.post(url, shipment_tag_creation_data)
    AssertionHelper.HTTP_400(response, error='This shipment already has a tag with the provided [tag_type] and [tag_value].')
Ejemplo n.º 22
0
 def test_cannot_approve_and_modify(self, new_access_request_bob,
                                    client_alice,
                                    access_request_rw_attributes):
     response = client_alice.patch(self.detail_url, {
         'approved': True,
         **access_request_rw_attributes
     })
     AssertionHelper.HTTP_400(
         response,
         'Only the requester can modify permissions in a pending or denied access request'
     )
Ejemplo n.º 23
0
    def test_with_device_blocked_on_shipment_fails(self, client_alice, route_attributes, shipment_alice_with_device):
        route_attributes['device_id'] = shipment_alice_with_device.device.id

        shipment_alice_with_device.pick_up()
        shipment_alice_with_device.save()

        with mock.patch('apps.shipments.models.Device.get_or_create_with_permission') as mock_device:
            mock_device.return_value = shipment_alice_with_device.device

            response = client_alice.post(self.url, route_attributes)
            AssertionHelper.HTTP_400(response, error='Device is already assigned to a Shipment in progress')
Ejemplo n.º 24
0
    def test_with_device_blocked_on_route_fails(self, client_alice, route_attributes, new_route_with_device, shipment):
        route_attributes['device_id'] = new_route_with_device.device.id

        new_route_with_device.routeleg_set.create(shipment=shipment)
        shipment.pick_up()
        shipment.save()

        with mock.patch('apps.shipments.models.Device.get_or_create_with_permission') as mock_device:
            mock_device.return_value = new_route_with_device.device
            response = client_alice.patch(self.url_route, route_attributes)
            AssertionHelper.HTTP_400(response, error='Device is already assigned to a Route in progress')
Ejemplo n.º 25
0
    def test_cant_request_no_permissions(self, client_bob):
        # All permissions default to NONE so a blank request should be rejected
        response = client_bob.post(self.list_url)
        AssertionHelper.HTTP_400(
            response,
            'Access requests must contain at least one requested permission')

        # A request that explicitly requests all NONE permissions should also be rejected
        response = client_bob.post(
            self.list_url, {
                'shipment_permission': PermissionLevel.NONE.name,
                'tags_permission': PermissionLevel.NONE.name,
                'documents_permission': PermissionLevel.NONE.name,
                'notes_permission': PermissionLevel.NONE.name,
                'tracking_permission': PermissionLevel.NONE.name,
                'telemetry_permission': PermissionLevel.NONE.name
            })
        AssertionHelper.HTTP_400(
            response,
            'Access requests must contain at least one requested permission')
Ejemplo n.º 26
0
    def test_requires_valid_expiration_date(self, client_alice):
        response = client_alice.post(
            self.url_permission_link_create, {
                'name': 'Permission Link Name',
                'expiration_date': datetime.utcnow() - timedelta(days=1)
            })

        AssertionHelper.HTTP_400(
            response,
            error='The expiration date should be greater than actual date',
            pointer='expiration_date')
Ejemplo n.º 27
0
 def test_approved_permissions_immutability(self,
                                            approved_access_request_bob,
                                            client_alice, client_bob,
                                            access_request_rw_attributes):
     assert approved_access_request_bob.approved is True
     for api_client in (client_alice, client_bob):
         response = api_client.patch(self.detail_url,
                                     access_request_rw_attributes)
         AssertionHelper.HTTP_400(
             response,
             'Cannot modify the permission level of an approved access request'
         )
Ejemplo n.º 28
0
 def test_tag_value_uniqueness(self, client_alice, org_id_alice, shipment):
     ShipmentTag.objects.create(
         tag_type=self.shipment_tags[0].tag_type,
         tag_value=self.shipment_tags[1].tag_value,
         shipment_id=shipment.id,
         owner_id=uuid.UUID(org_id_alice)
     ),
     response = client_alice.patch(getattr(self, f'url_{self.shipment_tags[0].tag_type}'), {
         'tag_value': self.shipment_tags[1].tag_value
     })
     AssertionHelper.HTTP_400(response,
                              'This shipment already has a tag with the provided [tag_type] and [tag_value].')
Ejemplo n.º 29
0
 def test_cant_request_no_permissions(self, client_bob):
     response = client_bob.patch(
         self.detail_url, {
             'shipment_permission': PermissionLevel.NONE.name,
             'tags_permission': PermissionLevel.NONE.name,
             'documents_permission': PermissionLevel.NONE.name,
             'notes_permission': PermissionLevel.NONE.name,
             'tracking_permission': PermissionLevel.NONE.name,
             'telemetry_permission': PermissionLevel.NONE.name
         })
     AssertionHelper.HTTP_400(
         response,
         'Access requests must contain at least one requested permission')
Ejemplo n.º 30
0
    def test_remove_device_in_progress_fails(self, client_alice, route_attributes, new_route_with_device, shipment):
        route_attributes['device_id'] = None

        new_route_with_device.routeleg_set.create(shipment=shipment)
        shipment.pick_up()
        shipment.save()

        response = client_alice.patch(self.url_route_device, data=route_attributes)
        print(response.json())
        AssertionHelper.HTTP_400(response, error='Cannot remove device from Route in progress')

        route = Route.objects.get(pk=new_route_with_device.id)
        assert route.device