feat: Initialize frontend with React, Vite, and Tailwind CSS
- Set up main entry point for React application. - Create About, Home, NotFound, Privacy, and Terms pages with SEO support. - Implement API service for file uploads and task management. - Add global styles using Tailwind CSS. - Create utility functions for SEO and text processing. - Configure Vite for development and production builds. - Set up Nginx configuration for serving frontend and backend. - Add scripts for cleanup of expired files and sitemap generation. - Implement deployment script for production environment.
This commit is contained in:
0
backend/tests/__init__.py
Normal file
0
backend/tests/__init__.py
Normal file
26
backend/tests/conftest.py
Normal file
26
backend/tests/conftest.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import os
|
||||
import pytest
|
||||
from app import create_app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app():
|
||||
"""Create application for testing."""
|
||||
os.environ['FLASK_ENV'] = 'testing'
|
||||
app = create_app()
|
||||
app.config.update({
|
||||
'TESTING': True,
|
||||
})
|
||||
yield app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(app):
|
||||
"""Flask test client."""
|
||||
return app.test_client()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def runner(app):
|
||||
"""Flask test CLI runner."""
|
||||
return app.test_cli_runner()
|
||||
21
backend/tests/test_compress.py
Normal file
21
backend/tests/test_compress.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""Tests for PDF compression endpoint."""
|
||||
import io
|
||||
|
||||
|
||||
def test_compress_pdf_no_file(client):
|
||||
"""POST /api/compress/pdf without file should return 400."""
|
||||
response = client.post('/api/compress/pdf')
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_compress_pdf_wrong_extension(client):
|
||||
"""POST /api/compress/pdf with non-PDF should return 400."""
|
||||
data = {
|
||||
'file': (io.BytesIO(b'hello'), 'test.docx'),
|
||||
}
|
||||
response = client.post(
|
||||
'/api/compress/pdf',
|
||||
data=data,
|
||||
content_type='multipart/form-data',
|
||||
)
|
||||
assert response.status_code == 400
|
||||
42
backend/tests/test_convert.py
Normal file
42
backend/tests/test_convert.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""Tests for file conversion endpoints."""
|
||||
import io
|
||||
|
||||
|
||||
def test_pdf_to_word_no_file(client):
|
||||
"""POST /api/convert/pdf-to-word without file should return 400."""
|
||||
response = client.post('/api/convert/pdf-to-word')
|
||||
assert response.status_code == 400
|
||||
data = response.get_json()
|
||||
assert 'error' in data
|
||||
|
||||
|
||||
def test_pdf_to_word_wrong_extension(client):
|
||||
"""POST /api/convert/pdf-to-word with non-PDF should return 400."""
|
||||
data = {
|
||||
'file': (io.BytesIO(b'hello world'), 'test.txt'),
|
||||
}
|
||||
response = client.post(
|
||||
'/api/convert/pdf-to-word',
|
||||
data=data,
|
||||
content_type='multipart/form-data',
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_word_to_pdf_no_file(client):
|
||||
"""POST /api/convert/word-to-pdf without file should return 400."""
|
||||
response = client.post('/api/convert/word-to-pdf')
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_word_to_pdf_wrong_extension(client):
|
||||
"""POST /api/convert/word-to-pdf with non-Word file should return 400."""
|
||||
data = {
|
||||
'file': (io.BytesIO(b'hello world'), 'test.pdf'),
|
||||
}
|
||||
response = client.post(
|
||||
'/api/convert/word-to-pdf',
|
||||
data=data,
|
||||
content_type='multipart/form-data',
|
||||
)
|
||||
assert response.status_code == 400
|
||||
15
backend/tests/test_health.py
Normal file
15
backend/tests/test_health.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""Tests for health check and app creation."""
|
||||
|
||||
|
||||
def test_health_endpoint(client):
|
||||
"""GET /api/health should return 200."""
|
||||
response = client.get('/api/health')
|
||||
assert response.status_code == 200
|
||||
data = response.get_json()
|
||||
assert data['status'] == 'healthy'
|
||||
|
||||
|
||||
def test_app_creates(app):
|
||||
"""App should create without errors."""
|
||||
assert app is not None
|
||||
assert app.config['TESTING'] is True
|
||||
27
backend/tests/test_image.py
Normal file
27
backend/tests/test_image.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""Tests for image conversion & resize endpoints."""
|
||||
import io
|
||||
|
||||
|
||||
def test_image_convert_no_file(client):
|
||||
"""POST /api/image/convert without file should return 400."""
|
||||
response = client.post('/api/image/convert')
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_image_resize_no_file(client):
|
||||
"""POST /api/image/resize without file should return 400."""
|
||||
response = client.post('/api/image/resize')
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_image_convert_wrong_type(client):
|
||||
"""POST /api/image/convert with non-image should return 400."""
|
||||
data = {
|
||||
'file': (io.BytesIO(b'not an image'), 'test.pdf'),
|
||||
}
|
||||
response = client.post(
|
||||
'/api/image/convert',
|
||||
data=data,
|
||||
content_type='multipart/form-data',
|
||||
)
|
||||
assert response.status_code == 400
|
||||
19
backend/tests/test_utils.py
Normal file
19
backend/tests/test_utils.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Tests for text utility functions."""
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add backend to path so we can import utils directly
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from app.utils.file_validator import validate_file
|
||||
from app.utils.sanitizer import generate_safe_path
|
||||
|
||||
|
||||
def test_generate_safe_path():
|
||||
"""generate_safe_path should produce UUID-based path."""
|
||||
path = generate_safe_path('uploads', 'test.pdf')
|
||||
assert path.startswith('uploads')
|
||||
assert path.endswith('.pdf')
|
||||
# Should contain a UUID directory
|
||||
parts = path.replace('\\', '/').split('/')
|
||||
assert len(parts) >= 3 # uploads / uuid / filename.pdf
|
||||
Reference in New Issue
Block a user