| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- using Admin.NET.Plugin.AiDOP.Infrastructure;
- using Admin.NET.Plugin.AiDOP.SmartOps;
- using Xunit;
- namespace Admin.NET.Plugin.AiDOP.Tests.DataPlatform;
- public class HomeGridLastKnownValueContractTests
- {
- private static readonly DateTime Today = new(2026, 9, 29);
- [Fact]
- public void LatestNoData_ShowsPreviousOk_AsLastKnown()
- {
- var card = HomeGridDisplayPolicy.Decide(
- Row(1, 3m, 10m, "OK", new DateTime(2026, 9, 23)),
- Row(2, null, null, "NO_DATA", new DateTime(2026, 9, 28)),
- 7, Today);
- Assert.Equal(3m, card.CurrentValue);
- Assert.Equal(10m, card.TargetValue);
- Assert.Equal("LAST_KNOWN_VALUE", card.DisplayState);
- Assert.Equal(new DateTime(2026, 9, 23), card.BizDate);
- Assert.Equal("NO_DATA", card.LatestResultStatus);
- Assert.Equal(new DateTime(2026, 9, 28), card.LatestBizDate);
- }
- [Fact]
- public void LatestOk_IsCurrentValue()
- {
- var card = HomeGridDisplayPolicy.Decide(
- Row(5, 1m, 2m, "OK", Today),
- Row(5, 1m, 2m, "OK", Today),
- 7, Today);
- Assert.Equal("CURRENT_VALUE", card.DisplayState);
- Assert.Equal(0, card.ValueAgeDays);
- Assert.Equal("FRESH", card.FreshnessState);
- }
- [Fact]
- public void NeverHadValue_IsNoData()
- {
- var card = HomeGridDisplayPolicy.Decide(
- null, Row(3, null, null, "NO_DATA", Today), 7, Today);
- Assert.Null(card.CurrentValue);
- Assert.Equal("NO_DATA", card.DisplayState);
- Assert.Equal("NO_VALUE", card.FreshnessState);
- }
- [Fact]
- public void SourceUnsupported_WithoutHistory_StaysUnsupported()
- {
- var card = HomeGridDisplayPolicy.Decide(
- null, Row(4, null, null, "SOURCE_UNSUPPORTED", Today), 7, Today);
- Assert.Equal("SOURCE_UNSUPPORTED", card.DisplayState);
- }
- [Fact]
- public void ValueAndTarget_ComeFromTheSameUsableRow()
- {
- var card = HomeGridDisplayPolicy.Decide(
- Row(8, 100m, 80m, "OK", new DateTime(2026, 9, 23)),
- Row(9, null, 1m, "NO_DATA", Today),
- 7, Today);
- Assert.Equal(100m, card.CurrentValue);
- Assert.Equal(80m, card.TargetValue);
- Assert.NotEqual(1m, card.TargetValue);
- }
- [Fact]
- public void BlankHistoricalStatus_IsNormalizedToOk()
- {
- var card = HomeGridDisplayPolicy.Decide(
- Row(6, 4m, null, "", new DateTime(2026, 9, 1)),
- Row(7, null, null, "NO_DATA", Today),
- 7, Today);
- Assert.Equal("OK", card.ResultStatus);
- Assert.Equal("NO_DATA", card.LatestResultStatus);
- }
- [Fact]
- public void DailySla_EightDaysIsStale_SevenDaysIsFresh()
- {
- var fresh = HomeGridDisplayPolicy.Decide(
- Row(1, 1m, null, "OK", Today.AddDays(-7)),
- Row(1, 1m, null, "OK", Today.AddDays(-7)),
- 7, Today);
- var stale = HomeGridDisplayPolicy.Decide(
- Row(1, 1m, null, "OK", Today.AddDays(-8)),
- Row(1, 1m, null, "OK", Today.AddDays(-8)),
- 7, Today);
- Assert.Equal("FRESH", fresh.FreshnessState);
- Assert.Equal("STALE", stale.FreshnessState);
- }
- [Fact]
- public void MonthlySla_ThirtyDaysFresh_FortySixDaysStale()
- {
- var fresh = HomeGridDisplayPolicy.Decide(
- Row(1, 1m, null, "OK", Today.AddDays(-30)),
- Row(1, 1m, null, "OK", Today.AddDays(-30)),
- 45, Today);
- var stale = HomeGridDisplayPolicy.Decide(
- Row(1, 1m, null, "OK", Today.AddDays(-46)),
- Row(1, 1m, null, "OK", Today.AddDays(-46)),
- 45, Today);
- Assert.Equal("FRESH", fresh.FreshnessState);
- Assert.Equal("STALE", stale.FreshnessState);
- }
- [Fact]
- public void MissingSla_IsPolicyMissing_NotFresh()
- {
- var card = HomeGridDisplayPolicy.Decide(
- Row(1, 1m, null, "OK", Today),
- Row(1, 1m, null, "OK", Today),
- null, Today);
- Assert.Equal("POLICY_MISSING", card.FreshnessState);
- }
- [Fact]
- public void FutureBizDate_ClampsAgeToZero()
- {
- var card = HomeGridDisplayPolicy.Decide(
- Row(1, 1m, null, "OK", Today.AddDays(2)),
- Row(1, 1m, null, "OK", Today.AddDays(2)),
- 7, Today);
- Assert.True(card.FutureBizDate);
- Assert.Equal(0, card.ValueAgeDays);
- Assert.Equal("FRESH", card.FreshnessState);
- }
- [Fact]
- public void Sql_UsesSameScope_AndDoesNotFallBackOutsideTheRange()
- {
- var source = File.ReadAllText(Path.Combine(RepoRoot(),
- "server", "Plugins", "Admin.NET.Plugin.AiDOP", "Controllers", "AidopKanbanController.Generic.cs"));
- Assert.Contains("ORDER BY v.biz_date DESC, v.calc_time DESC, v.id DESC", source);
- Assert.Equal(2, Count(source, "AND (@ds IS NULL OR v.biz_date>=@ds)"));
- Assert.Equal(2, Count(source, "AND (@de IS NULL OR v.biz_date<=@de)"));
- Assert.Contains("v.metric_value IS NOT NULL", source);
- Assert.Contains("v.result_status='OK' OR v.result_status IS NULL OR v.result_status=''", source);
- Assert.Contains("v.tenant_id=@t AND v.factory_id=@f AND v.module_code=@m", source);
- Assert.Contains("禁止拿未筛选的最后真实值补上", source);
- Assert.DoesNotContain("ToDictionary", Slice(source, "latestAttemptSql", "public async Task<IActionResult> GetDetailKpisGeneric"));
- }
- [Fact]
- public void FutureBizDateWarning_NamesOnlyTenantFactoryMetricAndDate()
- {
- var source = File.ReadAllText(Path.Combine(RepoRoot(),
- "server", "Plugins", "Admin.NET.Plugin.AiDOP", "Controllers", "AidopKanbanController.Generic.cs"));
- var i = source.IndexOf("home grid future biz date", StringComparison.Ordinal);
- Assert.True(i > 0);
- var window = source[i..(i + 220)];
- Assert.Contains("tenant={TenantId}", window);
- Assert.Contains("factory={FactoryId}", window);
- Assert.Contains("metric={MetricCode}", window);
- Assert.Contains("bizDate={BizDate}", window);
- Assert.DoesNotContain("resultReason", window, StringComparison.OrdinalIgnoreCase);
- }
- [Theory]
- [InlineData("S5_L1_003", "天", 45)]
- [InlineData("S5_L1_004", "天", 45)]
- [InlineData("S6_L1_003", "天", 45)]
- [InlineData("S7_L1_003", "天", 45)]
- [InlineData("S9_L1_001", "天", 45)]
- [InlineData("S8_L1_001", "实时", 1)]
- [InlineData("S1_L1_001", "天", 7)]
- public void SeedHelper_UsesMonthlyCodeThenRealtimeThenSeven(string code, string frequency, int expected)
- {
- Assert.Equal(expected, AidopKpiMasterSeed.ResolveFreshnessSlaDays(code, frequency));
- }
- private static HomeGridDisplayPolicy.Row Row(long id, decimal? value, decimal? target, string? status, DateTime bizDate) =>
- new()
- {
- Id = id,
- MetricValue = value,
- TargetValue = target,
- ResultStatus = status,
- BizDate = bizDate,
- };
- private static string RepoRoot()
- {
- var dir = new DirectoryInfo(AppContext.BaseDirectory);
- while (dir != null && !File.Exists(Path.Combine(dir.FullName, "AGENTS.md")))
- dir = dir.Parent;
- return dir?.FullName ?? throw new InvalidOperationException("repo root not found");
- }
- private static string Slice(string src, string start, string end)
- {
- var i = src.IndexOf(start, StringComparison.Ordinal);
- var j = src.IndexOf(end, i, StringComparison.Ordinal);
- Assert.True(i >= 0 && j > i);
- return src[i..j];
- }
- private static int Count(string src, string token)
- {
- var n = 0;
- var i = 0;
- while ((i = src.IndexOf(token, i, StringComparison.Ordinal)) >= 0)
- {
- n++;
- i += token.Length;
- }
- return n;
- }
- }
|