stop an existing .env from cancelling the defaults meant to replace it
پیشفرضهای دیروز روی یک سرورِ تازه کار میکردند ولی روی سرورِ واقعی نه، و تستِ با .env واقعی نشانش داد: هر دو حالتِ شایع خنثیشان میکرد. مقدارِ موجود ولی ناقص: .env سرور از قبل DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1 دارد. چون مقدار خالی نبود، کاملاً جایگزینِ پیشفرض میشد و دامنهی api.math.tadrisino2.ir باز هم غایب میماند — یعنی همان «Disallowed Host» قبلی، و باز هم ویرایشِ دستیِ فایل. حالا دامنههای خودمان به مقدارِ محیطی اضافه میشوند نه جایگزینش؛ همین برای CSRF_TRUSTED_ORIGINS و CORS_ALLOWED_ORIGINS هم اعمال شد. مقدارِ موجود ولی خالی: PUBLIC_BASE_URL در .env هست و خالی است، و os.environ.get فقط وقتی کلید *نباشد* پیشفرض میدهد. نتیجهاش paymentUrl نسبی و callbackِ خالیِ زرینپال بود — خرابیای که فقط موقعِ اولین پرداختِ واقعی معلوم میشود. حالا مقدارِ خالی هم به پیشفرض میافتد. این سهتا همانهاییاند که تا امروز مسئولِ سرور باید دستی به .env اضافه میکرد و چون در .env.example هم نبودند، هر بار از نو کشف میشدند. حالا در همان فایل مستند شدهاند و تست نگهبانشان است. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import logging
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import RequestFactory, SimpleTestCase, TestCase
|
||||
from rest_framework.test import APIClient
|
||||
@@ -306,3 +307,52 @@ class JSONLogFormatterTests(SimpleTestCase):
|
||||
self.assertEqual(payload['message'], 'something failed')
|
||||
self.assertIn('exception', payload)
|
||||
self.assertIn('ValueError: boom', payload['exception'])
|
||||
|
||||
|
||||
class ServerEnvDefaultsTests(SimpleTestCase):
|
||||
"""
|
||||
متغیرهایی که قبلاً مسئولِ سرور مجبور بود دستی به .env اضافه کند.
|
||||
|
||||
هر سهتا یک الگو داشتند: نبودشان یا سرویس را میخواباند یا یک مسیر را
|
||||
بیسروصدا میشکست، و چون در .env.example هم نبودند، هر بار از نو کشف
|
||||
میشدند. این تست نگهبانِ همان است — نه اینکه مقدارها «قشنگ»اند، بلکه
|
||||
اینکه بدونِ هیچ متغیرِ محیطیای مقدارِ کارآمد دارند.
|
||||
"""
|
||||
|
||||
HOST = 'api.math.tadrisino2.ir'
|
||||
|
||||
def test_the_api_domain_is_allowed_without_any_env_var(self):
|
||||
self.assertIn(self.HOST, settings.DEFAULT_ALLOWED_HOSTS)
|
||||
|
||||
def test_an_incomplete_env_value_does_not_drop_our_domains(self):
|
||||
"""
|
||||
.env سرور از قبل DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1 دارد.
|
||||
اگر مقدارِ موجود پیشفرض را کنار بزند، همان «Disallowed Host» قدیمی
|
||||
برمیگردد و باز کسی باید دستی فایل را ویرایش کند.
|
||||
"""
|
||||
# settings فقط نامهای بزرگ را نشان میدهد؛ تابع از خودِ ماژول میآید.
|
||||
from config.settings import _with_defaults
|
||||
|
||||
with patch.dict(os.environ, {'DJANGO_ALLOWED_HOSTS': 'localhost,127.0.0.1'}):
|
||||
merged = _with_defaults('DJANGO_ALLOWED_HOSTS', settings.DEFAULT_ALLOWED_HOSTS)
|
||||
self.assertIn(self.HOST, merged)
|
||||
self.assertIn('localhost', merged, 'مقدارِ موجود نباید حذف شود')
|
||||
|
||||
def test_a_present_but_empty_value_still_falls_back(self):
|
||||
"""کلید در .env هست ولی خالی — os.environ.get پیشفرض نمیدهد."""
|
||||
with patch.dict(os.environ, {'PUBLIC_BASE_URL': ''}):
|
||||
value = (os.environ.get('PUBLIC_BASE_URL', '').strip()
|
||||
or 'https://api.math.tadrisino2.ir')
|
||||
self.assertTrue(value.startswith('https://'))
|
||||
|
||||
def test_admin_login_origin_is_trusted_without_any_env_var(self):
|
||||
self.assertIn(f'https://{self.HOST}', settings.CSRF_TRUSTED_ORIGINS)
|
||||
|
||||
def test_the_deployed_frontend_may_call_the_api(self):
|
||||
self.assertIn('https://math.tadrisino2.ir', settings.CORS_ALLOWED_ORIGINS)
|
||||
|
||||
def test_payment_urls_are_absolute_without_any_env_var(self):
|
||||
"""خالی بودنِ PUBLIC_BASE_URL مسیرِ پرداخت را بیصدا میشکست."""
|
||||
self.assertTrue(settings.PUBLIC_BASE_URL.startswith('https://'))
|
||||
self.assertTrue(settings.ZARINPAL_CALLBACK_URL.startswith('https://'))
|
||||
self.assertIn('/api/payment/zarinpal/callback', settings.ZARINPAL_CALLBACK_URL)
|
||||
|
||||
Reference in New Issue
Block a user