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})
def test_create_multiple_access_requests(self, shipment_alice, client_bob, access_request_ro_attributes, access_request_rw_attributes, user_bob_id): response = client_bob.post(self.list_url, access_request_ro_attributes) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='AccessRequest', attributes={ **{ 'requester_id': user_bob_id }, **access_request_ro_attributes })) response = client_bob.post(self.list_url, access_request_rw_attributes) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='AccessRequest', attributes={ **{ 'requester_id': user_bob_id }, **access_request_rw_attributes }))
def assert_write_access(self, client, shipment_access=None, tags_access=None, documents_access=None, notes_access=None, all_access=None): if all_access is not None: shipment_access = all_access tags_access = all_access documents_access = all_access notes_access = all_access shipment_data = {'carriers_scac': 'h4x3d'} tag_data = { 'tag_type': 'foo', 'tag_value': 'bar', 'owner_id': client.handler._force_user.id, } document_data = { 'name': 'Test BOL', 'file_type': 'PDF', 'document_type': 'AIR_WAYBILL' } note_data = {'message': 'hello, world.'} if shipment_access is not None: response = client.patch(self.endpoint_urls['shipment'], shipment_data) AssertionHelper.HTTP_202( response) if shipment_access else AssertionHelper.HTTP_403( response) if tags_access is not None: response = client.post(self.endpoint_urls['tags'], tag_data) AssertionHelper.HTTP_201( response) if tags_access else AssertionHelper.HTTP_403( response) if documents_access is not None: response = client.post(self.endpoint_urls['documents'], document_data) AssertionHelper.HTTP_201( response) if documents_access else AssertionHelper.HTTP_403( response) if notes_access is not None: response = client.post(self.endpoint_urls['notes'], note_data) AssertionHelper.HTTP_201( response) if notes_access else AssertionHelper.HTTP_403( response)
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)
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)
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_with_unassociated_device(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_device.return_value = device response = client_alice.post(self.url, route_attributes) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='Route', attributes={ 'name': route_attributes['name'], 'driver_id': route_attributes['driver_id'], }, relationships={ 'device': AssertionHelper.EntityRef( resource='Device', pk=route_attributes['device_id'] ), } ), included=AssertionHelper.EntityRef( resource='Device', pk=route_attributes['device_id'] ), )
def test_permission_link_email_send_multiform(self, client_alice, mock_aws_success, user_alice): multi_form_data, content_type = create_form_content({ 'name': 'Permission Link Name', 'emails': ['*****@*****.**', '*****@*****.**'] }) response = client_alice.post(self.url_permission_link_create, multi_form_data, content_type=content_type) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={'name': 'Permission Link Name'}, relationships=self.shipment_alice_relationships)) assert len(mail.outbox) == 1 assert 'The ShipChain team' in str(mail.outbox[0].body) assert user_alice.username in str(mail.outbox[0].body) assert user_alice.username in str(mail.outbox[0].subject) pm_id = response.json()['data']['id'] mock_aws_success.assert_calls([{ 'path': '/test/', 'query': None, 'body': { 'long_url': f'http://localhost:3000/shipments/{self.shipment_alice.id}/?permission_link={pm_id}', 'expiration_date': None }, 'host': settings.URL_SHORTENER_HOST }])
def test_owner_can_create(self, client_alice): response = client_alice.post(self.url_permission_link_create, {'name': 'Permission Link Name'}) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={'name': 'Permission Link Name'}, relationships=self.shipment_alice_relationships))
def test_can_create_with_permission(self, client_bob, mock_successful_wallet_owner_calls): response = client_bob.post(self.url_permission_link_create, {'name': 'Permission Link Name'}) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={'name': 'Permission Link Name'}, relationships=self.shipment_alice_relationships)) mock_successful_wallet_owner_calls.assert_calls( self.successful_wallet_owner_calls_assertions)
def test_with_attributes(self, client_alice, route_attributes): response = client_alice.post(self.url, route_attributes) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='Route', attributes={ 'name': route_attributes['name'], 'driver_id': route_attributes['driver_id'], }, ), )
def test_org_shipment(self, client_alice, leg_attributes, second_shipment): leg_attributes['shipment_id'] = second_shipment.pk response = client_alice.post(self.url_route, data=leg_attributes) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='RouteLeg', attributes={ 'shipment_id': second_shipment.pk, }, ) )
def test_with_permission_links(self, shipment_alice, client_bob, new_rw_access_request_bob, permission_link_shipment_alice): shipment_data = {'carriers_scac': 'h4x3d'} tag_data = { 'tag_type': 'foo', 'tag_value': 'bar', 'owner_id': client_bob.handler._force_user.id, } # Documents/notes are not accessible via permission link, tracking/telemetry is RO response = client_bob.get( f'{self.endpoint_urls["shipment"]}?permission_link={permission_link_shipment_alice.id}' ) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', relationships={ 'tags': AssertionHelper.EntityRef(resource='ShipmentTag', pk=self.tag.id) }), included=AssertionHelper.EntityRef(resource='ShipmentTag'), ) response = client_bob.patch( f'{self.endpoint_urls["shipment"]}?permission_link={permission_link_shipment_alice.id}', shipment_data) AssertionHelper.HTTP_403(response) response = client_bob.post( f'{self.endpoint_urls["tags"]}?permission_link={permission_link_shipment_alice.id}', tag_data) AssertionHelper.HTTP_403(response) new_rw_access_request_bob.approved = True new_rw_access_request_bob.save() response = client_bob.patch( f'{self.endpoint_urls["shipment"]}?permission_link={permission_link_shipment_alice.id}', shipment_data) AssertionHelper.HTTP_202(response) response = client_bob.post( f'{self.endpoint_urls["tags"]}?permission_link={permission_link_shipment_alice.id}', tag_data) AssertionHelper.HTTP_201(response)
def test_valid_expiration_date(self, client_alice): attributes = { 'name': 'Permission Link Name', 'expiration_date': datetime.utcnow() + timedelta(days=1) } response = client_alice.post(self.url_permission_link_create, attributes) attributes['expiration_date'] = attributes[ 'expiration_date'].isoformat() + 'Z' AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes=attributes, relationships=self.shipment_alice_relationships))
def test_create_shipment_note(api_client, shipment): url = reverse('shipment-notes-list', kwargs={ 'version': 'v1', 'shipment_pk': shipment.id }) bad_shipment_url = reverse('shipment-notes-list', kwargs={ 'version': 'v1', 'shipment_pk': random_id() }) create_note_data, content_type = create_form_content({ 'message': MESSAGE, 'user_id': USER_ID }) # An unauthenticated user cannot create a shipment note without specifying the user response = api_client.post(url, {'message': MESSAGE}) AssertionHelper.HTTP_400(response, error='This field is required.', pointer='user_id') # A shipment note cannot be created for a non existing shipment response = api_client.post(bad_shipment_url, create_note_data, content_type=content_type) AssertionHelper.HTTP_403( response, error='You do not have permission to perform this action.') # An authenticated user with a specified user can create a shipment note response = api_client.post(url, create_note_data, content_type=content_type) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='ShipmentNote', attributes={ 'message': MESSAGE, 'user_id': USER_ID, 'username': None }, relationships={ 'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id) }))
def test_permission_link_email_wallet_owner( self, client_bob, mock_aws_success, user_bob, ): response = client_bob.post( self.url_permission_link_create, { 'name': 'Permission Link Name', 'emails': ['*****@*****.**', '*****@*****.**'], 'expiration_date': datetime.utcnow() + timedelta(days=1) }) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={ 'name': 'Permission Link Name', 'expiration_date': (datetime.utcnow() + timedelta(days=1)).isoformat() + 'Z' }, relationships=self.shipment_alice_relationships)) pm_id = response.json()['data']['id'] self.successful_wallet_owner_calls_assertions.append({ 'path': '/test/', 'query': None, 'body': { 'long_url': f'http://localhost:3000/shipments/{self.shipment_alice.id}/?permission_link={pm_id}', 'expiration_date': (datetime.utcnow() + timedelta(days=1)).isoformat() + '+00:00' }, 'host': settings.URL_SHORTENER_HOST }) mock_aws_success.assert_calls( self.successful_wallet_owner_calls_assertions) assert len(mail.outbox) == 1 assert 'The ShipChain team' in str(mail.outbox[0].body) assert user_bob.username in str(mail.outbox[0].body) assert user_bob.username in str(mail.outbox[0].subject)
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].')
def test_shipment_wallet_permission(self, client_bob, mock_successful_wallet_owner_calls, entity_ref_shipment_alice, successful_wallet_owner_calls_assertions): attributes = { 'name': 'Test BOL', 'file_type': FileType.PDF.name, 'document_type': DocumentType.AIR_WAYBILL.name } response = client_bob.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 } )) mock_successful_wallet_owner_calls.assert_calls(successful_wallet_owner_calls_assertions)
def test_no_attributes(self, client_alice, user_alice): response = client_alice.post(self.url) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='Route', ))
def test_shipment_not_included(self, shipment_alice, client_bob, access_request_ro_attributes): response = client_bob.post(self.list_url, {**access_request_ro_attributes}) AssertionHelper.HTTP_201(response) assert 'included' not in response.json()
def test_owner_is_caller_org(self, client_alice, org_id_alice): response = client_alice.post(self.url) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='Route', attributes={'owner_id': org_id_alice} ))
def test_owner_is_caller_no_org(self, client_lionel, user_lionel_id): response = client_lionel.post(self.url) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='Route', attributes={'owner_id': user_lionel_id} ))