S8NotificationLayerResolverTests.cs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using Admin.NET.Plugin.AiDOP.Service.S8;
  2. using Xunit;
  3. namespace Admin.NET.Plugin.AiDOP.Tests.S8;
  4. /// <summary>
  5. /// S8NotificationLayerResolver 静态契约单元测试。
  6. /// 实例方法 DispatchByLayerAsync 依赖 SqlSugarRepository + S8RoleResolver + S8NotificationPushAdapter,
  7. /// 在带 DB 的集成环境(dev DB seed: scene_code=S8_DEMO_DEFAULT/severity=HIGH/target=sys_admin/channel=SignalR)验证。
  8. /// 本文件覆盖渠道解析契约 + 静态防御。
  9. /// </summary>
  10. public class S8NotificationLayerResolverTests
  11. {
  12. [Fact]
  13. public void ParseChannels_NullOrEmpty_ReturnsEmpty()
  14. {
  15. Assert.Empty(S8NotificationLayerResolver.ParseChannels(null));
  16. Assert.Empty(S8NotificationLayerResolver.ParseChannels(""));
  17. Assert.Empty(S8NotificationLayerResolver.ParseChannels(" "));
  18. }
  19. [Fact]
  20. public void ParseChannels_Comma_TrimsAndSplits()
  21. {
  22. var r = S8NotificationLayerResolver.ParseChannels(" SignalR , Email , DingTalk ");
  23. Assert.Equal(new[] { "SignalR", "Email", "DingTalk" }, r);
  24. }
  25. [Fact]
  26. public void ParseChannels_Semicolon_AlsoSupported()
  27. {
  28. var r = S8NotificationLayerResolver.ParseChannels("Email;Sms;WorkWeixin");
  29. Assert.Equal(new[] { "Email", "Sms", "WorkWeixin" }, r);
  30. }
  31. [Fact]
  32. public void ParseChannels_Mixed_DropsEmpty()
  33. {
  34. var r = S8NotificationLayerResolver.ParseChannels("SignalR,;Email,,Sms");
  35. Assert.Equal(new[] { "SignalR", "Email", "Sms" }, r);
  36. }
  37. [Fact]
  38. public void DispatchByLayerInput_DefaultsAreSafe()
  39. {
  40. var x = new S8NotificationLayerResolver.DispatchByLayerInput();
  41. Assert.Equal(string.Empty, x.SceneCode);
  42. Assert.Equal(string.Empty, x.Severity);
  43. Assert.Equal(string.Empty, x.Title);
  44. Assert.Equal(string.Empty, x.Content);
  45. Assert.Null(x.ExceptionId);
  46. Assert.Null(x.ExceptionNo);
  47. Assert.Null(x.JumpUrl);
  48. Assert.False(x.Recovered);
  49. }
  50. [Fact]
  51. public void DispatchByLayerInput_RecoveredFlag_Settable()
  52. {
  53. var x = new S8NotificationLayerResolver.DispatchByLayerInput { Recovered = true };
  54. Assert.True(x.Recovered);
  55. }
  56. /// <summary>
  57. /// 验证 recovered 字段在 payload summary 中的布尔解析契约:
  58. /// Context["recovered"]="true"(大小写不敏感)→ true;其余 → false。
  59. /// </summary>
  60. [Theory]
  61. [InlineData("true", true)]
  62. [InlineData("True", true)]
  63. [InlineData("TRUE", true)]
  64. [InlineData("false", false)]
  65. [InlineData("", false)]
  66. [InlineData(null, false)]
  67. public void RecoveredContextValue_ParsesCorrectly(string? raw, bool expected)
  68. {
  69. var result = "true".Equals(raw, StringComparison.OrdinalIgnoreCase);
  70. Assert.Equal(expected, result);
  71. }
  72. }