chore: 更新项目文档与忽略规则,移除旧镜像归档跟踪
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from openpyxl import Workbook
|
||||
|
||||
from app import create_app
|
||||
from app.config import Config
|
||||
from app.extensions import db
|
||||
from app.models import Asset, AssetLogEntry, SimulationSetting
|
||||
from app.services.log_book_importer import import_log_book_data
|
||||
|
||||
|
||||
class TestConfig(Config):
|
||||
TESTING = True
|
||||
SECRET_KEY = "test"
|
||||
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
|
||||
|
||||
|
||||
class FirstStageFixTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.app = create_app(TestConfig)
|
||||
self.client = self.app.test_client()
|
||||
with self.app.app_context():
|
||||
db.create_all()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
with self.app.app_context():
|
||||
db.session.remove()
|
||||
db.drop_all()
|
||||
|
||||
def test_log_book_import_uses_state_nodes_and_imports_sub_log_events(self) -> None:
|
||||
workbook = Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "ST-01"
|
||||
sheet.append(["Log", "Start", "End", "Detail", "Sub log", None, None, "Location"])
|
||||
sheet.append(
|
||||
[
|
||||
"Mars transfer",
|
||||
datetime(2060, 1, 1),
|
||||
datetime(2060, 1, 10),
|
||||
"Outbound mission",
|
||||
"2060-01-02 Reached Mars orbit",
|
||||
None,
|
||||
None,
|
||||
"LEO",
|
||||
]
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
path = Path(temp_dir) / "log_book.xlsx"
|
||||
workbook.save(path)
|
||||
with self.app.app_context():
|
||||
summary = import_log_book_data(path)
|
||||
entries = db.session.query(AssetLogEntry).order_by(AssetLogEntry.start_at).all()
|
||||
|
||||
self.assertEqual(summary.imported_assets[0].state_entries, 1)
|
||||
self.assertEqual(summary.imported_assets[0].event_entries, 1)
|
||||
self.assertEqual([entry.entry_kind for entry in entries], ["state", "event"])
|
||||
self.assertEqual(entries[0].state_nodes[0].target_location, "LEO")
|
||||
self.assertEqual(entries[0].state_nodes[0].state_label, "Mars transfer")
|
||||
self.assertEqual(entries[1].state_nodes[0].target_location, "Mars")
|
||||
|
||||
def test_dashboard_attributes_only_events_within_thirty_days(self) -> None:
|
||||
with self.app.app_context():
|
||||
db.session.add(SimulationSetting(key="current_time", value="2060-03-12T09:00"))
|
||||
alpha = Asset(name="Alpha", asset_type="Vehicle")
|
||||
beta = Asset(name="Beta", asset_type="Vehicle")
|
||||
alpha.log_entries.extend(
|
||||
[
|
||||
AssetLogEntry(
|
||||
entry_kind="event",
|
||||
title="Alpha event",
|
||||
start_at=datetime(2060, 3, 20, tzinfo=timezone.utc),
|
||||
),
|
||||
AssetLogEntry(
|
||||
entry_kind="event",
|
||||
title="Too far away",
|
||||
start_at=datetime(2060, 5, 1, tzinfo=timezone.utc),
|
||||
),
|
||||
]
|
||||
)
|
||||
beta.log_entries.append(
|
||||
AssetLogEntry(
|
||||
entry_kind="event",
|
||||
title="Beta event",
|
||||
start_at=datetime(2060, 3, 21, tzinfo=timezone.utc),
|
||||
)
|
||||
)
|
||||
db.session.add_all([alpha, beta])
|
||||
db.session.commit()
|
||||
|
||||
response = self.client.get("/")
|
||||
page = response.get_data(as_text=True)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn("Alpha: Alpha event", page)
|
||||
self.assertIn("Beta: Beta event", page)
|
||||
self.assertNotIn("Beta: Alpha event", page)
|
||||
self.assertNotIn("Too far away", page)
|
||||
|
||||
def test_simulation_time_endpoint_persists_through_model(self) -> None:
|
||||
response = self.client.post(
|
||||
"/api/v1/sim-time",
|
||||
json={"sim_time": "2061-04-05T06:07"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
with self.app.app_context():
|
||||
setting = db.session.get(SimulationSetting, "current_time")
|
||||
self.assertIsNotNone(setting)
|
||||
self.assertEqual(setting.value, "2061-04-05T06:07")
|
||||
|
||||
def test_location_and_timeline_json_escape_script_terminators(self) -> None:
|
||||
payload = "Probe </script><script>alert(1)</script>"
|
||||
with self.app.app_context():
|
||||
asset = Asset(name=payload, asset_type="Station", home_region="LEO")
|
||||
asset.log_entries.append(
|
||||
AssetLogEntry(
|
||||
entry_kind="event",
|
||||
title=payload,
|
||||
start_at=datetime(2060, 3, 1, tzinfo=timezone.utc),
|
||||
)
|
||||
)
|
||||
db.session.add(asset)
|
||||
db.session.commit()
|
||||
|
||||
for path in ("/mission-preview/location-board", "/mission-preview/timeline"):
|
||||
response = self.client.get(path)
|
||||
page = response.get_data(as_text=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotIn(payload, page)
|
||||
self.assertIn("\\u003c/script\\u003e", page)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user