| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- """Test admin management API routes."""
- import pytest
- from flask_bcrypt import Bcrypt
- from app import db
- from app.models.admin import Admin
- @pytest.fixture
- def bcrypt_instance(app):
- """Create bcrypt instance for testing."""
- bcrypt = Bcrypt(app)
- return bcrypt
- @pytest.fixture
- def test_admin(app, db_session, bcrypt_instance):
- """Create a test admin for authentication tests."""
- with app.app_context():
- password_hash = bcrypt_instance.generate_password_hash('testpassword123').decode('utf-8')
- admin = Admin(
- username='testadmin',
- password_hash=password_hash
- )
- db.session.add(admin)
- db.session.commit()
- yield admin
- @pytest.fixture
- def auth_token(client, test_admin):
- """Get a valid JWT token for testing protected endpoints."""
- response = client.post('/api/auth/login', json={
- 'username': 'testadmin',
- 'password': 'testpassword123'
- })
- return response.get_json()['data']['token']
- @pytest.fixture
- def auth_headers(auth_token):
- """Get headers with JWT token for authenticated requests."""
- return {'Authorization': f'Bearer {auth_token}'}
- def test_list_admins(client, test_admin, auth_headers):
- """Test listing all admins."""
- response = client.get('/api/admins', headers=auth_headers)
-
- assert response.status_code == 200
- data = response.get_json()
- assert data['success'] is True
- assert len(data['data']) == 1
- assert data['data'][0]['username'] == 'testadmin'
- # Ensure password_hash is not exposed
- assert 'password_hash' not in data['data'][0]
- def test_list_admins_unauthorized(client, test_admin):
- """Test listing admins without auth returns 401."""
- response = client.get('/api/admins')
-
- assert response.status_code == 401
- def test_get_admin_by_id(client, test_admin, auth_headers):
- """Test getting admin by ID."""
- response = client.get(f'/api/admins/{test_admin.id}', headers=auth_headers)
-
- assert response.status_code == 200
- data = response.get_json()
- assert data['success'] is True
- assert data['data']['username'] == 'testadmin'
- assert 'password_hash' not in data['data']
- def test_get_admin_not_found(client, test_admin, auth_headers):
- """Test getting non-existent admin returns 404."""
- response = client.get('/api/admins/9999', headers=auth_headers)
-
- assert response.status_code == 404
- data = response.get_json()
- assert data['success'] is False
- assert data['code'] == 'NOT_FOUND'
- def test_create_admin(client, test_admin, auth_headers):
- """Test creating a new admin."""
- response = client.post('/api/admins/create',
- headers=auth_headers,
- json={
- 'username': 'newadmin',
- 'password': 'newpassword123'
- }
- )
-
- assert response.status_code == 201
- data = response.get_json()
- assert data['success'] is True
- assert data['data']['username'] == 'newadmin'
- assert 'password_hash' not in data['data']
- def test_create_admin_duplicate_username(client, test_admin, auth_headers):
- """Test creating admin with duplicate username returns 400."""
- response = client.post('/api/admins/create',
- headers=auth_headers,
- json={
- 'username': 'testadmin', # Already exists
- 'password': 'somepassword123'
- }
- )
-
- assert response.status_code == 400
- data = response.get_json()
- assert data['success'] is False
- assert '已存在' in data['error']
- def test_create_admin_short_password(client, test_admin, auth_headers):
- """Test creating admin with short password returns 400."""
- response = client.post('/api/admins/create',
- headers=auth_headers,
- json={
- 'username': 'newadmin',
- 'password': '12345' # Less than 6 characters
- }
- )
-
- assert response.status_code == 400
- data = response.get_json()
- assert data['success'] is False
- assert '至少' in data['error'] or '6' in data['error']
- def test_create_admin_empty_username(client, test_admin, auth_headers):
- """Test creating admin with empty username returns 400."""
- response = client.post('/api/admins/create',
- headers=auth_headers,
- json={
- 'username': '',
- 'password': 'validpassword123'
- }
- )
-
- assert response.status_code == 400
- data = response.get_json()
- assert data['success'] is False
- def test_update_admin(client, test_admin, auth_headers):
- """Test updating admin information."""
- response = client.post('/api/admins/update',
- headers=auth_headers,
- json={
- 'id': test_admin.id,
- 'username': 'updatedadmin'
- }
- )
-
- assert response.status_code == 200
- data = response.get_json()
- assert data['success'] is True
- assert data['data']['username'] == 'updatedadmin'
- def test_update_admin_password(client, test_admin, auth_headers):
- """Test updating admin password."""
- response = client.post('/api/admins/update',
- headers=auth_headers,
- json={
- 'id': test_admin.id,
- 'password': 'newpassword456'
- }
- )
-
- assert response.status_code == 200
-
- # Verify new password works
- login_response = client.post('/api/auth/login', json={
- 'username': 'testadmin',
- 'password': 'newpassword456'
- })
- assert login_response.status_code == 200
- def test_update_admin_not_found(client, test_admin, auth_headers):
- """Test updating non-existent admin returns 404."""
- response = client.post('/api/admins/update',
- headers=auth_headers,
- json={
- 'id': 9999,
- 'username': 'newname'
- }
- )
-
- assert response.status_code == 404
- def test_delete_admin(client, app, db_session, bcrypt_instance, auth_headers):
- """Test deleting an admin (when there are multiple)."""
- # Create a second admin first
- with app.app_context():
- password_hash = bcrypt_instance.generate_password_hash('password123').decode('utf-8')
- admin2 = Admin(username='admin2', password_hash=password_hash)
- db.session.add(admin2)
- db.session.commit()
- admin2_id = admin2.id
-
- # Delete the second admin
- response = client.post('/api/admins/delete',
- headers=auth_headers,
- json={'id': admin2_id}
- )
-
- assert response.status_code == 200
- data = response.get_json()
- assert data['success'] is True
- def test_delete_last_admin(client, test_admin, auth_headers):
- """Test deleting the last admin returns 400."""
- response = client.post('/api/admins/delete',
- headers=auth_headers,
- json={'id': test_admin.id}
- )
-
- assert response.status_code == 400
- data = response.get_json()
- assert data['success'] is False
- assert '最后' in data['error'] or '管理员' in data['error']
- def test_delete_admin_not_found(client, test_admin, auth_headers):
- """Test deleting non-existent admin returns 404."""
- response = client.post('/api/admins/delete',
- headers=auth_headers,
- json={'id': 9999}
- )
-
- assert response.status_code == 404
- data = response.get_json()
- assert data['success'] is False
- assert data['code'] == 'NOT_FOUND'
|