mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-29 01:08:59 +00:00
ADD - extend CityWarn browser mocks
Provide English active and archived population warnings plus stateful publish, update, resolve, and read-only scenarios for live preview. Extend the browser smoke suite to verify CityWarn bootstrap content and publisher access.
This commit is contained in:
@@ -5437,6 +5437,140 @@ const easyShareCatalog = [
|
||||
}))
|
||||
let easyShareVisibility = 'everyone'
|
||||
|
||||
let cityWarnSequence = 4
|
||||
let cityWarnAlerts = [
|
||||
{
|
||||
area: {
|
||||
centerX: 425.1,
|
||||
centerY: -979.5,
|
||||
label: 'Mission Row & Textile City',
|
||||
radius: 900,
|
||||
type: 'radius',
|
||||
},
|
||||
authorName: 'Jordan Hayes',
|
||||
body: 'Police have closed the area around Mission Row. Avoid access roads and follow instructions from emergency personnel.',
|
||||
category: 'police',
|
||||
createdAt: Date.now() - 11 * 60 * 1000,
|
||||
expiresAt: Date.now() + 49 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000001',
|
||||
instructions:
|
||||
'Stay outside the marked area. Use Elgin Avenue or Strawberry Avenue as alternate routes.',
|
||||
revision: 2,
|
||||
severity: 'danger',
|
||||
sourceLabel: 'Los Santos Police Department',
|
||||
startsAt: Date.now() - 11 * 60 * 1000,
|
||||
status: 'active',
|
||||
title: 'Police operation in Mission Row',
|
||||
updatedAt: Date.now() - 4 * 60 * 1000,
|
||||
updates: [
|
||||
{
|
||||
actorName: 'Jordan Hayes',
|
||||
createdAt: Date.now() - 4 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000012',
|
||||
kind: 'update',
|
||||
message: 'The closure has been extended to Textile City.',
|
||||
},
|
||||
{
|
||||
actorName: 'Jordan Hayes',
|
||||
createdAt: Date.now() - 11 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000011',
|
||||
kind: 'published',
|
||||
message: 'Police operation in Mission Row',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
area: {
|
||||
centerX: 1177.2,
|
||||
centerY: -1453.6,
|
||||
label: 'El Burro Heights',
|
||||
radius: null,
|
||||
type: 'district',
|
||||
},
|
||||
authorName: 'Maya Torres',
|
||||
body: 'Following a damaged water main, pressure fluctuations and temporary outages may occur in the eastern part of the city.',
|
||||
category: 'infrastructure',
|
||||
createdAt: Date.now() - 38 * 60 * 1000,
|
||||
expiresAt: Date.now() + 142 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000002',
|
||||
instructions:
|
||||
'Keep drinking water available as a precaution. Emergency services are not affected.',
|
||||
revision: 1,
|
||||
severity: 'warning',
|
||||
sourceLabel: 'Los Santos Fire Department',
|
||||
startsAt: Date.now() - 38 * 60 * 1000,
|
||||
status: 'active',
|
||||
title: 'Water supply disruption',
|
||||
updatedAt: Date.now() - 38 * 60 * 1000,
|
||||
updates: [
|
||||
{
|
||||
actorName: 'Maya Torres',
|
||||
createdAt: Date.now() - 38 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000021',
|
||||
kind: 'published',
|
||||
message: 'Water supply disruption',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
area: {
|
||||
centerX: null,
|
||||
centerY: null,
|
||||
label: 'Los Santos',
|
||||
radius: null,
|
||||
type: 'city',
|
||||
},
|
||||
authorName: 'Maya Torres',
|
||||
body: 'The technical fault in the city radio network has been resolved.',
|
||||
category: 'public_safety',
|
||||
createdAt: Date.now() - 27 * 60 * 60 * 1000,
|
||||
expiresAt: Date.now() - 26 * 60 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000003',
|
||||
instructions: 'No further action is required.',
|
||||
revision: 2,
|
||||
severity: 'information',
|
||||
sourceLabel: 'City Administration',
|
||||
startsAt: Date.now() - 27 * 60 * 60 * 1000,
|
||||
status: 'resolved',
|
||||
title: 'City radio network restored',
|
||||
updatedAt: Date.now() - 26 * 60 * 60 * 1000,
|
||||
updates: [
|
||||
{
|
||||
actorName: 'Maya Torres',
|
||||
createdAt: Date.now() - 26 * 60 * 60 * 1000,
|
||||
id: 'f074ea9d-45ab-4d90-9057-000000000032',
|
||||
kind: 'resolved',
|
||||
message: 'All systems are operating normally again.',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
function cityWarnBootstrap(testScenario) {
|
||||
const readonly = testScenario === 'citywarn-readonly'
|
||||
return {
|
||||
active: cityWarnAlerts.filter(
|
||||
(alert) => alert.status === 'active' && alert.expiresAt > Date.now(),
|
||||
),
|
||||
archive: cityWarnAlerts.filter(
|
||||
(alert) => alert.status !== 'active' || alert.expiresAt <= Date.now(),
|
||||
),
|
||||
context: {
|
||||
allowedCategories: readonly
|
||||
? []
|
||||
: ['public_safety', 'police', 'infrastructure', 'evacuation'],
|
||||
canCityWide: !readonly,
|
||||
canPublish: !readonly,
|
||||
gradeLabel: readonly ? null : 'Sergeant',
|
||||
jobLabel: readonly ? null : 'Los Santos Police Department',
|
||||
maximumSeverity: readonly ? null : 'extreme',
|
||||
onDuty: !readonly,
|
||||
requiresDuty: true,
|
||||
},
|
||||
onlinePlayers: 127,
|
||||
}
|
||||
}
|
||||
|
||||
function easyShareHistoryForScenario(testScenario) {
|
||||
if (testScenario === 'easyshare-empty') return []
|
||||
if (testScenario === 'easyshare-incoming') {
|
||||
@@ -5463,6 +5597,112 @@ app.post('/api/:endpoint', (request, response) => {
|
||||
response.json({ success: true })
|
||||
return
|
||||
}
|
||||
const cityWarnReadonly = testScenario === 'citywarn-readonly'
|
||||
if (endpoint === 'citywarn:bootstrap') {
|
||||
response.json({ success: true, data: cityWarnBootstrap(testScenario) })
|
||||
return
|
||||
}
|
||||
if (
|
||||
['citywarn:publish', 'citywarn:update', 'citywarn:resolve'].includes(
|
||||
endpoint,
|
||||
) &&
|
||||
cityWarnReadonly
|
||||
) {
|
||||
response.json({ success: false, error: 'not_authorized' })
|
||||
return
|
||||
}
|
||||
if (endpoint === 'citywarn:publish') {
|
||||
const title = String(request.body.title ?? '').trim()
|
||||
const body = String(request.body.body ?? '').trim()
|
||||
const area = request.body.area
|
||||
if (!title || !body || !area?.label || !area?.type) {
|
||||
response.json({ success: false, error: 'invalid_warning' })
|
||||
return
|
||||
}
|
||||
const now = Date.now()
|
||||
const alert = {
|
||||
area: {
|
||||
centerX: area.centerX == null ? null : Number(area.centerX),
|
||||
centerY: area.centerY == null ? null : Number(area.centerY),
|
||||
label: String(area.label),
|
||||
radius: area.radius == null ? null : Number(area.radius),
|
||||
type: String(area.type),
|
||||
},
|
||||
authorName: 'Jordan Hayes',
|
||||
body,
|
||||
category: String(request.body.category),
|
||||
createdAt: now,
|
||||
expiresAt: now + Number(request.body.durationMinutes ?? 60) * 60000,
|
||||
id: `f074ea9d-45ab-4d90-9057-${String(cityWarnSequence++).padStart(12, '0')}`,
|
||||
instructions: String(request.body.instructions ?? ''),
|
||||
revision: 1,
|
||||
severity: String(request.body.severity),
|
||||
sourceLabel: 'Los Santos Police Department',
|
||||
startsAt: now,
|
||||
status: 'active',
|
||||
title,
|
||||
updatedAt: now,
|
||||
updates: [
|
||||
{
|
||||
actorName: 'Jordan Hayes',
|
||||
createdAt: now,
|
||||
id: randomUUID(),
|
||||
kind: 'published',
|
||||
message: title,
|
||||
},
|
||||
],
|
||||
}
|
||||
cityWarnAlerts.unshift(alert)
|
||||
response.json({ success: true, data: { alert, recipients: 127 } })
|
||||
return
|
||||
}
|
||||
if (endpoint === 'citywarn:update') {
|
||||
const alert = cityWarnAlerts.find((item) => item.id === request.body.id)
|
||||
const message = String(request.body.message ?? '').trim()
|
||||
if (!alert || alert.status !== 'active') {
|
||||
response.json({ success: false, error: 'not_found' })
|
||||
return
|
||||
}
|
||||
if (!message || alert.revision !== Number(request.body.revision)) {
|
||||
response.json({ success: false, error: 'revision_conflict' })
|
||||
return
|
||||
}
|
||||
alert.revision += 1
|
||||
alert.updatedAt = Date.now()
|
||||
alert.updates.unshift({
|
||||
actorName: 'Jordan Hayes',
|
||||
createdAt: alert.updatedAt,
|
||||
id: randomUUID(),
|
||||
kind: 'update',
|
||||
message,
|
||||
})
|
||||
response.json({ success: true, data: { alert } })
|
||||
return
|
||||
}
|
||||
if (endpoint === 'citywarn:resolve') {
|
||||
const alert = cityWarnAlerts.find((item) => item.id === request.body.id)
|
||||
const message = String(request.body.message ?? '').trim()
|
||||
if (!alert || alert.status !== 'active') {
|
||||
response.json({ success: false, error: 'not_found' })
|
||||
return
|
||||
}
|
||||
if (!message || alert.revision !== Number(request.body.revision)) {
|
||||
response.json({ success: false, error: 'revision_conflict' })
|
||||
return
|
||||
}
|
||||
alert.revision += 1
|
||||
alert.status = 'resolved'
|
||||
alert.updatedAt = Date.now()
|
||||
alert.updates.unshift({
|
||||
actorName: 'Jordan Hayes',
|
||||
createdAt: alert.updatedAt,
|
||||
id: randomUUID(),
|
||||
kind: 'resolved',
|
||||
message,
|
||||
})
|
||||
response.json({ success: true, data: { alert } })
|
||||
return
|
||||
}
|
||||
const canManageWeazelNews = testScenario !== 'weazel-readonly'
|
||||
if (endpoint === 'weazel-news:context') {
|
||||
response.json({
|
||||
|
||||
@@ -15,6 +15,7 @@ const browserDataRequests = [
|
||||
['billing:overview', {}],
|
||||
['billing:list', { filter: 'all', limit: 20, offset: 0 }],
|
||||
['calendar:list', { endsAt: 4_102_444_800, startsAt: 0 }],
|
||||
['citywarn:bootstrap', {}],
|
||||
['calls:recents', {}],
|
||||
['companies:list', {}],
|
||||
['companies:my-requests', { limit: 20, offset: 0 }],
|
||||
@@ -152,6 +153,15 @@ function verifyBrowserTestData(dataByEndpoint) {
|
||||
3,
|
||||
)
|
||||
expectItems(dataByEndpoint.get('calendar:list'), 'calendar events', 5)
|
||||
const cityWarn = dataByEndpoint.get('citywarn:bootstrap')
|
||||
expectItems(cityWarn.active, 'active CityWarn alerts', 2)
|
||||
expectItems(cityWarn.archive, 'CityWarn alert history')
|
||||
assert.equal(cityWarn.context.canPublish, true)
|
||||
assert.deepEqual(
|
||||
cityWarn.active.map((alert) => alert.title),
|
||||
['Police operation in Mission Row', 'Water supply disruption'],
|
||||
)
|
||||
assert.equal(cityWarn.archive[0].title, 'City radio network restored')
|
||||
expectItems(dataByEndpoint.get('calls:recents'), 'recent calls', 5)
|
||||
expectItems(dataByEndpoint.get('companies:list').companies, 'companies', 3)
|
||||
expectItems(dataByEndpoint.get('contacts:list'), 'contacts', 10)
|
||||
|
||||
Reference in New Issue
Block a user