from app import create_app from app.database import initialize_database, migrate_database from app.services import calculate_costs, invoice_period from datetime import datetime def make_app(tmp_path, name): return create_app({"TESTING": True, "SQLALCHEMY_DATABASE_URI": f"sqlite:///{tmp_path / name}"}) def test_health(tmp_path): app=make_app(tmp_path, "test.db") assert app.test_client().get('/health').json=={"status":"ok"} def test_costs_50_percent_vat(): result=calculate_costs(123,23,50) assert float(result['net'])==100.0 assert float(result['deductible_vat'])==11.5 assert float(result['final_cost'])==111.5 def test_invoice_period(): assert invoice_period(datetime(2026,7,15),15).endswith('01–15') assert invoice_period(datetime(2026,7,16),15).endswith('16–koniec') def test_admin_settings_ajax_has_working_route(tmp_path): app=make_app(tmp_path, "admin.db") client=app.test_client() client.post('/login',data={'email':'admin@example.com','password':'admin123!'}) response=client.post('/admin',data={'action':'settings','name':'Firma','entity_type':'JDG','vat_rate':'23','vat_deduction_percent':'50','invoice_split_day':'15','invoice_split_enabled':'on','region':'mazowieckie','theme':'darkly'},headers={'X-Requested-With':'XMLHttpRequest'}) assert response.status_code==200 assert response.json['ok'] is True def test_ure_brand_aggregation(tmp_path): from app.integrations.ure import aggregate_ure_companies app=make_app(tmp_path, "ure.db") with app.app_context(): rows=[{"nazwa":"ORLEN S.A.","nip":"7740001454","regon":"610188201","nazwaStacji":"100","wojewodztwo":"mazowieckie","benzynySilnikowe":True}, {"nazwa":"ORLEN S.A.","nip":"7740001454","regon":"610188201","nazwaStacji":"101","wojewodztwo":"śląskie","olejeNapedowe":True}] result=aggregate_ure_companies(rows) assert len(result)==1 assert result[0]["brand_name"]=="ORLEN" assert result[0]["station_count"]==2 def test_ure_duplicate_dkn_is_merged(tmp_path): from app.integrations.ure import aggregate_ure_companies app=make_app(tmp_path, "dup.db") rows=[ {"dkn":977,"nazwa":"Test Sp. z o.o.","nip":"123","nazwaStacji":"Punkt paliw","infraUlica":"A","infraNrLokalu":"1","infraPoczta":"Miasto","benzynySilnikowe":True}, {"dkn":977,"nazwa":"Test Sp. z o.o.","nip":"123","nazwaStacji":"Punkt paliw i LPG","infraUlica":"A","infraNrLokalu":"1","infraPoczta":"Miasto","gazPlynnyLPG":True}, ] with app.app_context(): result=aggregate_ure_companies(rows) assert len(result)==1 assert result[0]["station_count"]==1 assert len(result[0]["points"])==1 assert result[0]["points"][0]["has_petrol"] is True assert result[0]["points"][0]["has_lpg"] is True def test_company_and_card_forms_use_post(tmp_path): app=make_app(tmp_path, "forms.db") client=app.test_client() client.post('/login',data={'email':'admin@example.com','password':'admin123!'}) html=client.get('/admin/companies').get_data(as_text=True) assert 'action="/api/companies" method="post"' in html assert 'action="/api/fuel-cards" method="post"' in html assert 'Nazwa firmy' in html assert 'Operator karty' in html def test_cannot_delete_last_admin(tmp_path): app=make_app(tmp_path, "delete.db") client=app.test_client() client.post('/api/auth/login',data={'email':'admin@example.com','password':'admin123!'}) with app.app_context(): from app.models import User admin=User.query.filter_by(email='admin@example.com').first() admin_id=admin.id response=client.delete(f'/api/users/{admin_id}') assert response.status_code == 400 assert response.json['ok'] is False def test_cli_reset_admin_password(tmp_path): app=make_app(tmp_path, "cli.db") runner=app.test_cli_runner() result=runner.invoke(args=['reset-admin-password','--email','admin@example.com','--password','NoweHaslo123!']) assert result.exit_code == 0 client=app.test_client() response=client.post('/api/auth/login',data={'email':'admin@example.com','password':'NoweHaslo123!'}) assert response.status_code == 200 def test_html_cache_headers_and_static_versioning(tmp_path): app=make_app(tmp_path, "cache.db") client=app.test_client() response=client.get('/login') assert response.headers['Cache-Control'] == 'no-store, no-cache, private, must-revalidate' assert response.headers['Pragma'] == 'no-cache' assert response.headers['Expires'] == '0' html=response.get_data(as_text=True) assert '/static/css/layout.css?v=' in html assert '/static/js/core.js?v=' in html def test_css_cache_for_30_days(tmp_path): app=make_app(tmp_path, "static.db") response=app.test_client().get('/static/css/layout.css') assert response.status_code == 200 assert response.headers['Cache-Control'] == 'public, max-age=2592000, immutable' def test_create_app_initializes_database(tmp_path): from sqlalchemy import inspect from app.extensions import db app = create_app({"TESTING": True, "SQLALCHEMY_DATABASE_URI": f"sqlite:///{tmp_path / 'empty.db'}"}) with app.app_context(): tables = inspect(db.engine).get_table_names() assert "user" in tables assert "schema_migration" in tables def test_migration_runner_creates_registry_without_legacy_migrations(tmp_path): from sqlalchemy import inspect from app.extensions import db app = make_app(tmp_path, "migrations.db") with app.app_context(): assert migrate_database() == [] assert "schema_migration" in inspect(db.engine).get_table_names() assert migrate_database() == []