refactor(map): remove access gate
This commit is contained in:
@@ -138,6 +138,22 @@ assert.ok(stationNavigationUrl.startsWith('https://uri.amap.com/navigation?to=11
|
||||
assert.match(stationNavigationUrl, /%E5%B9%BF%E5%B7%9E/);
|
||||
assert.match(stationNavigationUrl, /coordinate=gaode&callnative=1$/);
|
||||
assert.equal(navigationUrlForEntity('vehicle', { plateNumber: '无位置车辆' }), null);
|
||||
const launchClassSet = new Set();
|
||||
const launchOverlay = { hidden: true, classList: { add(name) { launchClassSet.add(name); }, remove(name) { launchClassSet.delete(name); } } };
|
||||
const launchButton = { disabled: false, dataset: { navigationUrl: stationNavigationUrl }, classList: { add(name) { launchClassSet.add('button:' + name); }, remove(name) { launchClassSet.delete('button:' + name); }, contains(name) { return launchClassSet.has('button:' + name); } } };
|
||||
const launchTimers = [];
|
||||
document.getElementById = id => id === 'navigationLaunchOverlay' ? launchOverlay : id === 'detailNavigateBtn' ? launchButton : null;
|
||||
window.requestAnimationFrame = callback => callback();
|
||||
window.setTimeout = (callback, delay) => { launchTimers.push({ callback, delay }); return launchTimers.length; };
|
||||
window.clearTimeout = () => {};
|
||||
window.location = { assign() {} };
|
||||
selectedEntity = { mode: 'station', entity: dashboard.stations[0] };
|
||||
navigateToSelectedEntity();
|
||||
assert.equal(launchOverlay.hidden, false);
|
||||
assert.ok(launchClassSet.has('is-visible'));
|
||||
assert.ok(launchClassSet.has('button:is-launching'));
|
||||
assert.equal(launchButton.disabled, true);
|
||||
assert.deepEqual(launchTimers.map(timer => timer.delay), [140, 4000]);
|
||||
const stationView = stationViewportSummary();
|
||||
assert.equal(stationView.level, 'station');
|
||||
assert.equal(stationView.visibleNodes.length, 2);
|
||||
@@ -170,5 +186,7 @@ const sandbox = {
|
||||
setInterval() {},
|
||||
clearInterval() {}
|
||||
};
|
||||
assert.match(source, /navigationLaunchOverlay/);
|
||||
assert.match(source, /正在打开高德地图/);
|
||||
vm.runInNewContext(`${source}\n${checks}`, sandbox, { filename: 'app.js' });
|
||||
console.log('vehicle hierarchy aggregation tests: ok');
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import importlib.util
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
from pathlib import Path
|
||||
import time
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
@@ -14,7 +10,7 @@ SPEC.loader.exec_module(server)
|
||||
|
||||
|
||||
class DashboardTest(unittest.TestCase):
|
||||
def test_dashboard_aggregates_authorized_vehicle_and_station_data(self):
|
||||
def test_dashboard_aggregates_public_vehicle_and_station_data(self):
|
||||
def fake_post(path, body):
|
||||
if path.endswith("realtime/query"):
|
||||
return [
|
||||
@@ -45,55 +41,11 @@ class DashboardTest(unittest.TestCase):
|
||||
self.assertEqual(result["vehicles"][0]["dailyMileageKm"], 12.345)
|
||||
self.assertEqual(result["vehicles"][2]["dailyMileageKm"], 0)
|
||||
|
||||
def test_public_station_directory_uses_an_allowlist(self):
|
||||
stations = [{
|
||||
"id": "GD-1", "name": "广州合作站", "shortName": "合作站", "province": "广东省",
|
||||
"city": "广州市", "district": "黄埔区", "address": "开源大道1号", "longitude": 113.2,
|
||||
"latitude": 23.1, "cooperative": True, "monthlyHydrogenKg": 88.8,
|
||||
"totalHydrogenKg": 999.9, "internalOwner": "must-not-leak",
|
||||
}]
|
||||
with patch.object(server, "_post_open_platform", return_value=stations):
|
||||
with patch.object(server, "_cache", {}):
|
||||
result = server._load_public_stations()
|
||||
|
||||
station = result["stations"][0]
|
||||
self.assertEqual(result["access"]["level"], "public")
|
||||
self.assertEqual(station["name"], "广州合作站")
|
||||
self.assertTrue(station["cooperative"])
|
||||
self.assertNotIn("monthlyHydrogenKg", station)
|
||||
self.assertNotIn("totalHydrogenKg", station)
|
||||
self.assertNotIn("internalOwner", station)
|
||||
|
||||
def test_static_asset_version_is_a_content_fingerprint(self):
|
||||
self.assertEqual(len(server.STATIC_ASSET_VERSION), 16)
|
||||
self.assertRegex(server.STATIC_ASSET_VERSION, r"^[0-9a-f]{16}$")
|
||||
index_template = (Path(__file__).parents[1] / "index.html").read_text(encoding="utf-8")
|
||||
self.assertEqual(index_template.count("__ASSET_VERSION__"), 2)
|
||||
|
||||
def test_signed_operations_session_requires_the_operations_scope(self):
|
||||
with patch.object(server, "LOCAL_ACCESS_CODE", "LN-map-test-code"), patch.object(server, "SESSION_SECRET", b"test-session-secret"), patch.object(server, "SESSION_TTL_SECONDS", 600):
|
||||
principal = server._authorizer().authorize_access_code("LN-map-test-code")
|
||||
token = server._create_session(principal)
|
||||
session = server._read_session(f"{server.SESSION_COOKIE_NAME}={token}")
|
||||
|
||||
self.assertEqual(session["subject"], "local-access-code")
|
||||
self.assertIn(server.OPERATIONS_READ_SCOPE, session["scopes"])
|
||||
self.assertIsNone(server._read_session(f"{server.SESSION_COOKIE_NAME}={token}tampered"))
|
||||
|
||||
legacy_payload = {"v": 1, "sub": "legacy", "scopes": [server.OPERATIONS_READ_SCOPE], "exp": 4_102_444_800}
|
||||
legacy_encoded = server._b64encode(server._json_bytes(legacy_payload))
|
||||
legacy_signature = server._b64encode(hmac.new(server.SESSION_SECRET, legacy_encoded.encode("ascii"), hashlib.sha256).digest())
|
||||
self.assertIsNone(server._read_session(f"{server.SESSION_COOKIE_NAME}={legacy_encoded}.{legacy_signature}"))
|
||||
|
||||
def test_default_operations_session_expires_after_thirty_minutes(self):
|
||||
self.assertEqual(server.SESSION_TTL_SECONDS, 1800)
|
||||
with patch.object(server, "SESSION_SECRET", b"test-session-secret"), patch.object(server, "SESSION_TTL_SECONDS", 1800):
|
||||
token = server._create_session({"subject": "test", "scopes": [server.OPERATIONS_READ_SCOPE]})
|
||||
encoded, _ = token.split(".", 1)
|
||||
payload = json.loads(server._b64decode(encoded))
|
||||
self.assertGreaterEqual(payload["exp"], int(time.time()) + 1798)
|
||||
self.assertLessEqual(payload["exp"], int(time.time()) + 1801)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user