feat(platform): include no-data service status
This commit is contained in:
@@ -326,6 +326,18 @@ func TestHandlerVehicleServiceSummaryEndpoint(t *testing.T) {
|
|||||||
if len(body.Data.ServiceStatuses) == 0 || len(body.Data.Protocols) == 0 {
|
if len(body.Data.ServiceStatuses) == 0 || len(body.Data.Protocols) == 0 {
|
||||||
t.Fatalf("summary should expose service status and protocol distributions, got %+v", body.Data)
|
t.Fatalf("summary should expose service status and protocol distributions, got %+v", body.Data)
|
||||||
}
|
}
|
||||||
|
noDataStatusFound := false
|
||||||
|
for _, status := range body.Data.ServiceStatuses {
|
||||||
|
if status.Status == "no_data" {
|
||||||
|
noDataStatusFound = true
|
||||||
|
if status.Title != "暂无数据来源" || status.Count != body.Data.NoDataVehicles {
|
||||||
|
t.Fatalf("no_data service status should mirror noDataVehicles, got status=%+v summary=%+v", status, body.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !noDataStatusFound {
|
||||||
|
t.Fatalf("summary service status distribution should include no_data, got %+v", body.Data.ServiceStatuses)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandlerVehicleServiceOverviewsEndpoint(t *testing.T) {
|
func TestHandlerVehicleServiceOverviewsEndpoint(t *testing.T) {
|
||||||
|
|||||||
@@ -180,7 +180,13 @@ func (m *MockStore) VehicleServiceSummary(ctx context.Context) (VehicleServiceSu
|
|||||||
ServiceStatuses: []ServiceStatusStat{},
|
ServiceStatuses: []ServiceStatusStat{},
|
||||||
Protocols: []ProtocolStat{},
|
Protocols: []ProtocolStat{},
|
||||||
}
|
}
|
||||||
statusCounts := map[string]*ServiceStatusStat{}
|
statusCounts := map[string]*ServiceStatusStat{
|
||||||
|
"healthy": {Status: "healthy", Title: "服务正常"},
|
||||||
|
"degraded": {Status: "degraded", Title: "部分来源离线"},
|
||||||
|
"offline": {Status: "offline", Title: "车辆离线"},
|
||||||
|
"no_data": {Status: "no_data", Title: "暂无数据来源"},
|
||||||
|
"identity_required": {Status: "identity_required", Title: "身份未绑定"},
|
||||||
|
}
|
||||||
protocolCounts := map[string]*ProtocolStat{}
|
protocolCounts := map[string]*ProtocolStat{}
|
||||||
for _, row := range coverage.Items {
|
for _, row := range coverage.Items {
|
||||||
if row.BindingStatus == "bound" {
|
if row.BindingStatus == "bound" {
|
||||||
@@ -678,6 +684,8 @@ func keepServiceStatus(status *VehicleServiceStatus, raw string) bool {
|
|||||||
return status != nil && status.Status == "identity_required"
|
return status != nil && status.Status == "identity_required"
|
||||||
case "offline":
|
case "offline":
|
||||||
return status != nil && status.Status == "offline"
|
return status != nil && status.Status == "offline"
|
||||||
|
case "no_data":
|
||||||
|
return status != nil && status.Status == "no_data"
|
||||||
case "degraded":
|
case "degraded":
|
||||||
return status != nil && status.Status == "degraded"
|
return status != nil && status.Status == "degraded"
|
||||||
case "healthy":
|
case "healthy":
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ func (s *ProductionStore) serviceStatusStats(ctx context.Context) ([]ServiceStat
|
|||||||
{Status: "healthy", Title: "服务正常"},
|
{Status: "healthy", Title: "服务正常"},
|
||||||
{Status: "degraded", Title: "部分来源离线"},
|
{Status: "degraded", Title: "部分来源离线"},
|
||||||
{Status: "offline", Title: "车辆离线"},
|
{Status: "offline", Title: "车辆离线"},
|
||||||
|
{Status: "no_data", Title: "暂无数据来源"},
|
||||||
{Status: "identity_required", Title: "身份未绑定"},
|
{Status: "identity_required", Title: "身份未绑定"},
|
||||||
}
|
}
|
||||||
out := make([]ServiceStatusStat, 0, len(definitions))
|
out := make([]ServiceStatusStat, 0, len(definitions))
|
||||||
@@ -150,6 +151,7 @@ GROUP BY v.vin
|
|||||||
{Status: "healthy", Title: "服务正常", Count: healthy},
|
{Status: "healthy", Title: "服务正常", Count: healthy},
|
||||||
{Status: "degraded", Title: "部分来源离线", Count: degraded},
|
{Status: "degraded", Title: "部分来源离线", Count: degraded},
|
||||||
{Status: "offline", Title: "车辆离线", Count: offline},
|
{Status: "offline", Title: "车辆离线", Count: offline},
|
||||||
|
{Status: "no_data", Title: "暂无数据来源", Count: summary.NoDataVehicles},
|
||||||
{Status: "identity_required", Title: "身份未绑定", Count: summary.IdentityRequiredVehicles},
|
{Status: "identity_required", Title: "身份未绑定", Count: summary.IdentityRequiredVehicles},
|
||||||
}
|
}
|
||||||
protocols, err := s.protocolStats(ctx)
|
protocols, err := s.protocolStats(ctx)
|
||||||
|
|||||||
@@ -153,7 +153,10 @@ test('vehicleServiceSummary reads the vehicle service summary endpoint', async (
|
|||||||
multiSourceVehicles: 181,
|
multiSourceVehicles: 181,
|
||||||
noDataVehicles: 461,
|
noDataVehicles: 461,
|
||||||
identityRequiredVehicles: 9,
|
identityRequiredVehicles: 9,
|
||||||
serviceStatuses: [{ status: 'healthy', title: '服务正常', count: 161 }],
|
serviceStatuses: [
|
||||||
|
{ status: 'healthy', title: '服务正常', count: 161 },
|
||||||
|
{ status: 'no_data', title: '暂无数据来源', count: 461 }
|
||||||
|
],
|
||||||
protocols: [{ protocol: 'JT808', online: 157, total: 388 }]
|
protocols: [{ protocol: 'JT808', online: 157, total: 388 }]
|
||||||
},
|
},
|
||||||
traceId: 'trace-test',
|
traceId: 'trace-test',
|
||||||
@@ -166,6 +169,7 @@ test('vehicleServiceSummary reads the vehicle service summary endpoint', async (
|
|||||||
expect(fetchMock).toHaveBeenCalledWith('/api/vehicle-service/summary', undefined);
|
expect(fetchMock).toHaveBeenCalledWith('/api/vehicle-service/summary', undefined);
|
||||||
expect(result.totalVehicles).toBe(1033);
|
expect(result.totalVehicles).toBe(1033);
|
||||||
expect(result.multiSourceVehicles).toBe(181);
|
expect(result.multiSourceVehicles).toBe(181);
|
||||||
|
expect(result.serviceStatuses.find((item) => item.status === 'no_data')?.count).toBe(461);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('api errors include backend message, detail, and trace id', async () => {
|
test('api errors include backend message, detail, and trace id', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user