595 lines
24 KiB
Python
595 lines
24 KiB
Python
from django.test import TestCase, Client
|
|
from django.contrib.auth.models import Permission
|
|
from knox.models import AuthToken
|
|
from django.utils import timezone
|
|
|
|
from authentication.models import ExtendedUser
|
|
from inventory.models import Event, Item, Container
|
|
from tickets.models import IssueThread
|
|
from shipments.models import Shipment
|
|
|
|
|
|
class ShipmentApiTest(TestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
# Create a test user with all permissions
|
|
self.user = ExtendedUser.objects.create_user('testuser', 'test@example.com', 'test')
|
|
self.user.user_permissions.add(*Permission.objects.all())
|
|
self.user.save()
|
|
|
|
# Create authentication token
|
|
self.token = AuthToken.objects.create(user=self.user)
|
|
self.client = Client(headers={'Authorization': 'Token ' + self.token[1]})
|
|
|
|
# Create test event and container
|
|
self.event = Event.objects.create(slug='test-event', name='Test Event')
|
|
self.container = Container.objects.create(name='Test Container')
|
|
|
|
# Create test items with container
|
|
self.item1 = Item.objects.create(description='Test Item 1', event=self.event, container=self.container)
|
|
self.item2 = Item.objects.create(description='Test Item 2', event=self.event, container=self.container)
|
|
|
|
# Create test ticket
|
|
self.ticket = IssueThread.objects.create(name='Test Ticket')
|
|
|
|
def test_list_shipments_empty(self):
|
|
"""Test listing shipments when none exist"""
|
|
response = self.client.get('/api/2/shipments/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json(), [])
|
|
|
|
def test_create_shipment(self):
|
|
"""Test creating a new shipment"""
|
|
data = {
|
|
'recipient_name': 'John Smith',
|
|
'street_address': '123 Oxford Street',
|
|
'city': 'London',
|
|
'state_province': 'Greater London',
|
|
'postal_code': 'W1D 2HG',
|
|
'country': 'United Kingdom',
|
|
'related_items': [],
|
|
'related_tickets': []
|
|
}
|
|
response = self.client.post('/api/2/shipments/', data, content_type='application/json')
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertEqual(response.json()['recipient_name'], 'John Smith')
|
|
self.assertEqual(response.json()['state'], Shipment.CREATED)
|
|
self.assertEqual(response.json()['review_requirement'], None)
|
|
|
|
# Retrieve the created shipment and verify its details
|
|
shipment_id = response.json()['id']
|
|
get_response = self.client.get(f'/api/2/shipments/{shipment_id}/')
|
|
self.assertEqual(get_response.status_code, 200)
|
|
self.assertEqual(get_response.json()['id'], shipment_id)
|
|
self.assertEqual(get_response.json()['recipient_name'], 'John Smith')
|
|
self.assertEqual(get_response.json()['street_address'], '123 Oxford Street')
|
|
self.assertEqual(get_response.json()['city'], 'London')
|
|
self.assertEqual(get_response.json()['state_province'], 'Greater London')
|
|
self.assertEqual(get_response.json()['postal_code'], 'W1D 2HG')
|
|
self.assertEqual(get_response.json()['country'], 'United Kingdom')
|
|
self.assertEqual(get_response.json()['state'], Shipment.CREATED)
|
|
self.assertEqual(get_response.json()['review_requirement'], None)
|
|
|
|
def test_get_shipment(self):
|
|
"""Test retrieving a specific shipment"""
|
|
# Create a shipment first
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Maria Garcia',
|
|
street_address='Calle Gran Via 28',
|
|
city='Madrid',
|
|
state_province='Madrid',
|
|
postal_code='28013',
|
|
country='Spain'
|
|
)
|
|
|
|
response = self.client.get(f'/api/2/shipments/{shipment.id}/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['id'], shipment.id)
|
|
self.assertEqual(response.json()['recipient_name'], 'Maria Garcia')
|
|
|
|
def test_update_shipment(self):
|
|
"""Test updating a shipment"""
|
|
# Create a shipment first
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Hans Mueller',
|
|
street_address='Kurfürstendamm 216',
|
|
city='Berlin',
|
|
state_province='Berlin',
|
|
postal_code='10719',
|
|
country='Germany'
|
|
)
|
|
|
|
data = {
|
|
'recipient_name': 'Hans-Jürgen Mueller',
|
|
'address_supplements': 'Apartment 4B'
|
|
}
|
|
response = self.client.patch(f'/api/2/shipments/{shipment.id}/', data, content_type='application/json')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['recipient_name'], 'Hans-Jürgen Mueller')
|
|
self.assertEqual(response.json()['address_supplements'], 'Apartment 4B')
|
|
|
|
def test_delete_shipment(self):
|
|
"""Test deleting a shipment"""
|
|
# Create a shipment first
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Sophie Dubois',
|
|
street_address='15 Rue de Rivoli',
|
|
city='Paris',
|
|
state_province='Île-de-France',
|
|
postal_code='75001',
|
|
country='France'
|
|
)
|
|
|
|
response = self.client.delete(f'/api/2/shipments/{shipment.id}/')
|
|
self.assertEqual(response.status_code, 204)
|
|
|
|
# Verify it's soft deleted - use all_objects manager to see deleted items
|
|
self.assertTrue(Shipment.all_objects.filter(id=shipment.id).exists())
|
|
# Check if it's marked as deleted
|
|
shipment.refresh_from_db()
|
|
self.assertIsNotNone(shipment.deleted_at)
|
|
|
|
def test_add_items(self):
|
|
"""Test adding items to a shipment"""
|
|
# Create a shipment first
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Alessandro Romano',
|
|
street_address='Via del Corso 123',
|
|
city='Rome',
|
|
state_province='Lazio',
|
|
postal_code='00186',
|
|
country='Italy'
|
|
)
|
|
|
|
data = {
|
|
'item_ids': [self.item1.id, self.item2.id],
|
|
'review_requirement': Shipment.REVIEW_ITEMS
|
|
}
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/add_items/', data, content_type='application/json')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.PENDING_REVIEW)
|
|
self.assertEqual(response.json()['review_requirement'], Shipment.REVIEW_ITEMS)
|
|
|
|
# Verify items were added
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.related_items.count(), 2)
|
|
|
|
def test_approve_shipment(self):
|
|
"""Test approving a shipment"""
|
|
# Create a shipment and add items
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Yuki Tanaka',
|
|
street_address='1-1-1 Shibuya',
|
|
city='Tokyo',
|
|
state_province='Tokyo',
|
|
postal_code='150-0002',
|
|
country='Japan'
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
shipment.review_requirement = Shipment.REVIEW_ITEMS
|
|
shipment.state = Shipment.PENDING_REVIEW
|
|
shipment.save()
|
|
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/approve/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.READY_FOR_SHIPPING)
|
|
|
|
def test_reject_shipment(self):
|
|
"""Test rejecting a shipment"""
|
|
# Create a shipment and add items
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Carlos Rodriguez',
|
|
street_address='Avenida Insurgentes Sur 1602',
|
|
city='Mexico City',
|
|
state_province='CDMX',
|
|
postal_code='03940',
|
|
country='Mexico'
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
shipment.review_requirement = Shipment.REVIEW_ITEMS
|
|
shipment.state = Shipment.PENDING_REVIEW
|
|
shipment.save()
|
|
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/reject/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.REJECTED)
|
|
|
|
def test_mark_shipped(self):
|
|
"""Test marking a shipment as shipped"""
|
|
# Create a shipment and set it to READY_FOR_SHIPPING
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Anna Kowalski',
|
|
street_address='ul. Marszałkowska 126',
|
|
city='Warsaw',
|
|
state_province='Mazowieckie',
|
|
postal_code='00-008',
|
|
country='Poland',
|
|
state=Shipment.READY_FOR_SHIPPING
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/mark_shipped/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.SHIPPED)
|
|
self.assertIsNotNone(response.json()['shipped_at'])
|
|
|
|
def test_mark_completed(self):
|
|
"""Test marking a shipment as completed"""
|
|
# Create a shipment and set it to SHIPPED
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Lars Andersen',
|
|
street_address='Strøget 1',
|
|
city='Copenhagen',
|
|
state_province='Capital Region',
|
|
postal_code='1095',
|
|
country='Denmark',
|
|
state=Shipment.SHIPPED,
|
|
shipped_at=timezone.now()
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/mark_completed/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.COMPLETED)
|
|
self.assertIsNotNone(response.json()['completed_at'])
|
|
|
|
def test_invalid_state_transition(self):
|
|
"""Test that invalid state transitions are rejected"""
|
|
# Create a shipment in CREATED state
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Ahmed Hassan',
|
|
street_address='26 July Street',
|
|
city='Cairo',
|
|
state_province='Cairo Governorate',
|
|
postal_code='11511',
|
|
country='Egypt'
|
|
)
|
|
|
|
# Try to mark it as shipped directly (invalid transition)
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/mark_shipped/')
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertIn('error', response.json())
|
|
self.assertIn('Invalid state transition', response.json()['error'])
|
|
|
|
# Verify state hasn't changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.CREATED)
|
|
|
|
def test_add_items_without_review_requirement(self):
|
|
"""Test adding items without specifying review requirement"""
|
|
# Create a shipment first
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Wei Chen',
|
|
street_address='88 Century Avenue',
|
|
city='Shanghai',
|
|
state_province='Shanghai',
|
|
postal_code='200120',
|
|
country='China'
|
|
)
|
|
|
|
data = {
|
|
'item_ids': [self.item1.id, self.item2.id]
|
|
}
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/add_items/', data, content_type='application/json')
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertIn('error', response.json())
|
|
|
|
# Verify state hasn't changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.CREATED)
|
|
|
|
def test_approve_without_items(self):
|
|
"""Test approving a shipment without items"""
|
|
# Create a shipment with REVIEW_ITEMS requirement
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Raj Patel',
|
|
street_address='123 MG Road',
|
|
city='Mumbai',
|
|
state_province='Maharashtra',
|
|
postal_code='400001',
|
|
country='India',
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_ITEMS
|
|
)
|
|
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/approve/')
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertIn('error', response.json())
|
|
|
|
# Verify state hasn't changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.PENDING_REVIEW)
|
|
|
|
def test_approve_without_address(self):
|
|
"""Test approving a shipment without complete address"""
|
|
# Create a shipment with REVIEW_ADDRESS requirement
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Sofia Oliveira',
|
|
street_address='Avenida Paulista 1000',
|
|
city='São Paulo',
|
|
state_province='São Paulo',
|
|
postal_code='01310-100',
|
|
country='', # Missing country
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_ADDRESS
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
response = self.client.post(f'/api/2/shipments/{shipment.id}/approve/')
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertIn('error', response.json())
|
|
|
|
# Verify state hasn't changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.PENDING_REVIEW)
|
|
|
|
def test_public_shipment_detail_success(self):
|
|
"""Test retrieving shipment details via public API with valid public_secret"""
|
|
# Create a shipment in PENDING_REVIEW state
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='John Doe',
|
|
street_address='123 Main St',
|
|
city='Anytown',
|
|
state_province='State',
|
|
postal_code='12345',
|
|
country='Country',
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_ADDRESS
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test retrieving shipment details
|
|
response = public_client.get(f'/api/2/public/shipments/{shipment.public_secret}/')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['id'], shipment.id)
|
|
self.assertEqual(response.json()['recipient_name'], 'John Doe')
|
|
self.assertEqual(response.json()['state'], Shipment.PENDING_REVIEW)
|
|
self.assertEqual(len(response.json()['related_items']), 1)
|
|
|
|
def test_public_shipment_detail_not_found(self):
|
|
"""Test retrieving shipment details with non-existent public_secret"""
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test with non-existent public_secret
|
|
response = public_client.get('/api/2/public/shipments/00000000-0000-0000-0000-000000000000/')
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
def test_public_shipment_detail_wrong_state(self):
|
|
"""Test retrieving shipment details when shipment is not in PENDING_REVIEW state"""
|
|
# Create a shipment in CREATED state
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Jane Smith',
|
|
street_address='456 Oak Ave',
|
|
city='Somewhere',
|
|
state_province='Province',
|
|
postal_code='67890',
|
|
country='Nation',
|
|
state=Shipment.CREATED
|
|
)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test retrieving shipment details
|
|
response = public_client.get(f'/api/2/public/shipments/{shipment.public_secret}/')
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
def test_public_shipment_update_success_address_only(self):
|
|
"""Test updating shipment with address information when review_requirement is ADDRESS"""
|
|
# Create a shipment in PENDING_REVIEW state with ADDRESS review requirement
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Alice Johnson',
|
|
street_address='789 Pine Rd',
|
|
city='Nowhere',
|
|
state_province='Region',
|
|
postal_code='13579',
|
|
country='Land',
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_ADDRESS
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test updating shipment with address information
|
|
data = {
|
|
'recipient_name': 'Alice Johnson',
|
|
'street_address': '789 Pine Rd, Apt 4B',
|
|
'city': 'Nowhere',
|
|
'state_province': 'Region',
|
|
'postal_code': '13579',
|
|
'country': 'Land'
|
|
}
|
|
response = public_client.post(
|
|
f'/api/2/public/shipments/{shipment.public_secret}/update/',
|
|
data,
|
|
content_type='application/json'
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.READY_FOR_SHIPPING)
|
|
self.assertEqual(response.json()['street_address'], '789 Pine Rd, Apt 4B')
|
|
|
|
# Verify state has changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.READY_FOR_SHIPPING)
|
|
|
|
def test_public_shipment_update_success_both_review(self):
|
|
"""Test updating shipment with address information when review_requirement is BOTH"""
|
|
# Create a shipment in PENDING_REVIEW state with BOTH review requirement
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Bob Wilson',
|
|
street_address='321 Elm St',
|
|
city='Elsewhere',
|
|
state_province='Territory',
|
|
postal_code='24680',
|
|
country='Realm',
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_BOTH
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test updating shipment with address information
|
|
data = {
|
|
'recipient_name': 'Bob Wilson',
|
|
'street_address': '321 Elm St, Suite 7',
|
|
'city': 'Elsewhere',
|
|
'state_province': 'Territory',
|
|
'postal_code': '24680',
|
|
'country': 'Realm'
|
|
}
|
|
response = public_client.post(
|
|
f'/api/2/public/shipments/{shipment.public_secret}/update/',
|
|
data,
|
|
content_type='application/json'
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.READY_FOR_SHIPPING)
|
|
self.assertEqual(response.json()['street_address'], '321 Elm St, Suite 7')
|
|
|
|
# Verify state has changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.READY_FOR_SHIPPING)
|
|
|
|
def test_public_shipment_update_success_items_only(self):
|
|
"""Test updating shipment with address information when review_requirement is ITEMS"""
|
|
# Create a shipment in PENDING_REVIEW state with ITEMS review requirement
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Carol Davis',
|
|
street_address='654 Maple Dr',
|
|
city='Anywhere',
|
|
state_province='District',
|
|
postal_code='97531',
|
|
country='Kingdom',
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_ITEMS
|
|
)
|
|
shipment.related_items.add(self.item1)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test updating shipment with address information
|
|
data = {
|
|
'recipient_name': 'Carol Davis',
|
|
'street_address': '654 Maple Dr, Unit 3',
|
|
'city': 'Anywhere',
|
|
'state_province': 'District',
|
|
'postal_code': '97531',
|
|
'country': 'Kingdom'
|
|
}
|
|
response = public_client.post(
|
|
f'/api/2/public/shipments/{shipment.public_secret}/update/',
|
|
data,
|
|
content_type='application/json'
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()['state'], Shipment.PENDING_REVIEW) # State should not change
|
|
self.assertEqual(response.json()['street_address'], '654 Maple Dr, Unit 3')
|
|
|
|
# Verify state has not changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.PENDING_REVIEW)
|
|
|
|
def test_public_shipment_update_not_found(self):
|
|
"""Test updating shipment with non-existent public_secret"""
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test with non-existent public_secret
|
|
data = {
|
|
'recipient_name': 'Unknown Person',
|
|
'street_address': '123 Fake St',
|
|
'city': 'Fake City',
|
|
'state_province': 'Fake State',
|
|
'postal_code': '12345',
|
|
'country': 'Fake Country'
|
|
}
|
|
response = public_client.post(
|
|
'/api/2/public/shipments/00000000-0000-0000-0000-000000000000/update/',
|
|
data,
|
|
content_type='application/json'
|
|
)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
def test_public_shipment_update_wrong_state(self):
|
|
"""Test updating shipment when it's not in PENDING_REVIEW state"""
|
|
# Create a shipment in CREATED state
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='David Lee',
|
|
street_address='987 Cedar Ln',
|
|
city='Nowhere',
|
|
state_province='Province',
|
|
postal_code='13579',
|
|
country='Country',
|
|
state=Shipment.CREATED
|
|
)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test updating shipment
|
|
data = {
|
|
'recipient_name': 'David Lee',
|
|
'street_address': '987 Cedar Ln, Apt 2C',
|
|
'city': 'Nowhere',
|
|
'state_province': 'Province',
|
|
'postal_code': '13579',
|
|
'country': 'Country'
|
|
}
|
|
response = public_client.post(
|
|
f'/api/2/public/shipments/{shipment.public_secret}/update/',
|
|
data,
|
|
content_type='application/json'
|
|
)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
# Verify state hasn't changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.CREATED)
|
|
|
|
def test_public_shipment_update_both_review_missing_items(self):
|
|
"""Test updating shipment with BOTH review requirement when items are missing"""
|
|
# Create a shipment in PENDING_REVIEW state with BOTH review requirement but no items
|
|
shipment = Shipment.objects.create(
|
|
recipient_name='Eve Brown',
|
|
street_address='147 Birch Ave',
|
|
city='Somewhere',
|
|
state_province='Region',
|
|
postal_code='24680',
|
|
country='Land',
|
|
state=Shipment.PENDING_REVIEW,
|
|
review_requirement=Shipment.REVIEW_BOTH
|
|
)
|
|
|
|
# Create a client without authentication
|
|
public_client = Client()
|
|
|
|
# Test updating shipment with address information
|
|
data = {
|
|
'recipient_name': 'Eve Brown',
|
|
'street_address': '147 Birch Ave, Suite 5',
|
|
'city': 'Somewhere',
|
|
'state_province': 'Region',
|
|
'postal_code': '24680',
|
|
'country': 'Land'
|
|
}
|
|
response = public_client.post(
|
|
f'/api/2/public/shipments/{shipment.public_secret}/update/',
|
|
data,
|
|
content_type='application/json'
|
|
)
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertIn('error', response.json())
|
|
self.assertIn('Items must be added before approval', response.json()['error'])
|
|
|
|
# Verify state hasn't changed
|
|
shipment.refresh_from_db()
|
|
self.assertEqual(shipment.state, Shipment.PENDING_REVIEW)
|