mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-20 05:02:50 +08:00
parent
b9b228c9e1
commit
c088492cfa
2
.github/workflows/nightly-build.yml
vendored
2
.github/workflows/nightly-build.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [ 20.x ]
|
||||
node-version: [ 22.x ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [ 20.x ]
|
||||
node-version: [ 22.x ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
@ -25,7 +25,7 @@
|
||||
<Title>$(AssemblyName)</Title>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MinVer" Version="5.0.0">
|
||||
<PackageReference Include="MinVer" Version="6.0.0-rc.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0.0-preview.6 AS base
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0.0-preview.7 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 8080
|
||||
RUN apt update
|
||||
|
@ -39,6 +39,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B
|
||||
gen.id.linq = scripts/gen.id.linq
|
||||
gen.ln.cmd = scripts/gen.ln.cmd
|
||||
gen.resx.tt = scripts/gen.resx.tt
|
||||
git.del.obsolete.tags.ps1 = scripts/git.del.obsolete.tags.ps1
|
||||
image.optimize.csx = scripts/image.optimize.csx
|
||||
install.as.tpl.ps1 = scripts/install.as.tpl.ps1
|
||||
rename.csx = scripts/rename.csx
|
||||
@ -48,6 +49,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B
|
||||
switcher.nsext.json = scripts/switcher.nsext.json
|
||||
switcher.ps1 = scripts/switcher.ps1
|
||||
sync.sln.files.csx = scripts/sync.sln.files.csx
|
||||
wait.server.stop.sh = scripts/wait.server.stop.sh
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1129FE25-466B-4F4F-85FC-3752664245E1}"
|
||||
|
@ -49,6 +49,7 @@ XML注释文件不存在
|
||||
未获取到待执行任务
|
||||
模块名称不能为空
|
||||
模块说明不能为空
|
||||
此节点已下线
|
||||
民族不正确
|
||||
消息主题不能为空
|
||||
消息内容不能为空
|
||||
@ -65,6 +66,7 @@ XML注释文件不存在
|
||||
站内信不存在
|
||||
站内信状态不正确
|
||||
站内信类型不正确
|
||||
缓存键不能为空
|
||||
网络地址不正确
|
||||
菜单名称不能为空
|
||||
菜单标题不能为空
|
||||
|
@ -15,7 +15,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.19-preview">
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.20">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@ -23,7 +23,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.31.0.96804">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
2
scripts/git.del.obsolete.tags.ps1
Normal file
2
scripts/git.del.obsolete.tags.ps1
Normal file
@ -0,0 +1,2 @@
|
||||
git push origin :refs/tags/$(git tag -l "*-*")
|
||||
git tag -d $(git tag -l "*-*")
|
@ -10,11 +10,11 @@
|
||||
"packages": [
|
||||
{
|
||||
"packageName": "FreeSql.NS",
|
||||
"version": "3.2.833-preview20260627-ns1"
|
||||
"version": "3.2.833-ns4"
|
||||
},
|
||||
{
|
||||
"packageName": "FreeSql.DbContext.NS",
|
||||
"version": "3.2.833-preview20260627-ns1"
|
||||
"version": "3.2.833-ns4"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
28
scripts/wait.server.stop.sh
Normal file
28
scripts/wait.server.stop.sh
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 检查是否提供了 URL 参数
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <url>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 获取外部传入的 URL 参数
|
||||
URL="$1"
|
||||
|
||||
# 初始化返回值
|
||||
response=""
|
||||
|
||||
# 循环检查 API 返回值
|
||||
while [ "$response" != "1" ]; do
|
||||
# 等待一段时间再进行下一次检查,避免频繁请求
|
||||
sleep 1
|
||||
|
||||
# 使用 curl 请求 URL,并捕获返回值,忽略 SSL 证书错误
|
||||
response=$(curl -sk "$URL")
|
||||
|
||||
# 打印返回值 (可选)
|
||||
echo "$1: $response"
|
||||
done
|
||||
|
||||
# 当返回值为 "1" 时,继续执行后续脚本
|
||||
echo "API returned 1. Continuing with the script..."
|
@ -24,7 +24,9 @@ namespace NetAdmin.AdmServer.Host
|
||||
/// <summary>
|
||||
/// 配置应用程序中间件
|
||||
/// </summary>
|
||||
#pragma warning disable S2325
|
||||
public void Configure(IApplicationBuilder app, IHostApplicationLifetime lifeTime)
|
||||
#pragma warning restore S2325
|
||||
{
|
||||
_ = app //
|
||||
.UseMiddleware<SafetyShopHostMiddleware>() // 安全停机中间件
|
||||
@ -52,7 +54,9 @@ namespace NetAdmin.AdmServer.Host
|
||||
/// <summary>
|
||||
/// 配置服务容器
|
||||
/// </summary>
|
||||
#pragma warning disable S2325
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
#pragma warning restore S2325
|
||||
{
|
||||
_ = services.AddConsoleFormatter() // 添加控制台日志模板
|
||||
.AddAllOptions() // 添加配置项
|
||||
@ -75,12 +79,18 @@ namespace NetAdmin.AdmServer.Host
|
||||
|
||||
/// <inheritdoc />
|
||||
#pragma warning disable ASA001
|
||||
public Task<int> Execute(CommandContext context, CommandLineArgs settings)
|
||||
public async Task<int> Execute(CommandContext context, CommandLineArgs settings)
|
||||
#pragma warning restore ASA001
|
||||
{
|
||||
Args = settings;
|
||||
_ = Serve.Run(RunOptions.Default.WithArgs(context.Remaining.Raw.ToArray()));
|
||||
return Task.FromResult(0);
|
||||
var webOpt = new WebApplicationOptions //
|
||||
{
|
||||
EnvironmentName = Environment.GetEnvironmentVariable("TEST_ENVIRONMENT").NullOrEmpty(null)
|
||||
, Args = context.Remaining.Raw.ToArray()
|
||||
};
|
||||
Serve.BuildApplication(RunOptions.Default.ConfigureOptions(webOpt), null, out var startUrl, out var app);
|
||||
await app.RunAsync(startUrl).ConfigureAwait(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,6 @@
|
||||
<ProjectReference Include="../NetAdmin.AdmServer.Host/NetAdmin.AdmServer.Host.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0-release-24373-02"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -33,7 +33,7 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
||||
/// <summary>
|
||||
/// 导出实体
|
||||
/// </summary>
|
||||
protected async Task<IActionResult> ExportAsync<TQuery, TExport>( //
|
||||
protected static async Task<IActionResult> ExportAsync<TQuery, TExport>( //
|
||||
Func<QueryReq<TQuery>, ISelectGrouping<TEntity, TEntity>> selector, QueryReq<TQuery> query, string fileName
|
||||
, Expression<Func<ISelectGroupingAggregate<TEntity, TEntity>, object>> listExp = null)
|
||||
where TQuery : DataAbstraction, new()
|
||||
@ -45,7 +45,7 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
||||
/// <summary>
|
||||
/// 导出实体
|
||||
/// </summary>
|
||||
protected async Task<IActionResult> ExportAsync<TQuery, TExport>( //
|
||||
protected static async Task<IActionResult> ExportAsync<TQuery, TExport>( //
|
||||
Func<QueryReq<TQuery>, ISelect<TEntity>> selector, QueryReq<TQuery> query, string fileName
|
||||
, Expression<Func<TEntity, object>> listExp = null)
|
||||
where TQuery : DataAbstraction, new()
|
||||
|
@ -13,9 +13,21 @@ public abstract record MutableEntity : MutableEntity<long>
|
||||
/// <summary>
|
||||
/// 可变实体
|
||||
/// </summary>
|
||||
public abstract record MutableEntity<T> : LiteMutableEntity<T>, IFieldModifiedUser
|
||||
public abstract record MutableEntity<T> : LiteMutableEntity<T>, IFieldCreatedUser, IFieldModifiedUser
|
||||
where T : IEquatable<T>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[Column(CanUpdate = false, Position = -1)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? CreatedUserId { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string CreatedUserName { get; init; }
|
||||
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
[CsvIgnore]
|
||||
|
13
src/backend/NetAdmin.Domain/Dto/Sys/Cache/DelEntryReq.cs
Normal file
13
src/backend/NetAdmin.Domain/Dto/Sys/Cache/DelEntryReq.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:删除缓存项
|
||||
/// </summary>
|
||||
public sealed record DelEntryReq : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存键
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.缓存键不能为空))]
|
||||
public string Key { get; init; }
|
||||
}
|
17
src/backend/NetAdmin.Domain/Dto/Sys/Tool/ExecuteSqlReq.cs
Normal file
17
src/backend/NetAdmin.Domain/Dto/Sys/Tool/ExecuteSqlReq.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Tool;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:执行SQL
|
||||
/// </summary>
|
||||
public record ExecuteSqlReq : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// SQL 语句
|
||||
/// </summary>
|
||||
public string Sql { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 超时时间(秒)
|
||||
/// </summary>
|
||||
public int TimeoutSecs { get; init; }
|
||||
}
|
@ -10,6 +10,23 @@ namespace NetAdmin.Host.Controllers;
|
||||
[ApiDescriptionSettings("Probe")]
|
||||
public sealed class ProbeController : ControllerBase<ICache<IDistributedCache, IService>, IService>
|
||||
{
|
||||
/// <summary>
|
||||
/// 退出程序
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
#pragma warning disable CA1822
|
||||
public ActionResult Exit(string token)
|
||||
#pragma warning restore CA1822
|
||||
{
|
||||
if (token != GlobalStatic.SecretKey) {
|
||||
return new UnauthorizedResult();
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
return new OkResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 健康检查
|
||||
/// </summary>
|
||||
@ -23,6 +40,46 @@ public sealed class ProbeController : ControllerBase<ICache<IDistributedCache, I
|
||||
HostName = Environment.MachineName
|
||||
, CurrentConnections = SafetyShopHostMiddleware.Connections
|
||||
, GlobalStatic.ProductVersion
|
||||
, ThreadCounts = GlobalStatic.CurrentProcess.Threads.Count
|
||||
, GlobalStatic.LatestLogTime
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统是否已经安全停止
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
[NonUnify]
|
||||
#pragma warning disable CA1822, S3400
|
||||
public IActionResult IsSystemSafetyStopped(int logTimeoutSeconds = 15)
|
||||
#pragma warning restore S3400, CA1822
|
||||
{
|
||||
return new ContentResult {
|
||||
Content = (DateTime.Now - GlobalStatic.LatestLogTime).TotalSeconds >
|
||||
logTimeoutSeconds
|
||||
? "1"
|
||||
: "0"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实例下线
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 流量只出不进
|
||||
/// </remarks>
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
#pragma warning disable CA1822
|
||||
public ActionResult Offline(string token)
|
||||
#pragma warning restore CA1822
|
||||
{
|
||||
if (token != GlobalStatic.SecretKey) {
|
||||
return new UnauthorizedResult();
|
||||
}
|
||||
|
||||
SafetyShopHostMiddleware.Stop();
|
||||
return new OkResult();
|
||||
}
|
||||
}
|
19
src/backend/NetAdmin.Host/Extensions/MethodInfoExtensions.cs
Normal file
19
src/backend/NetAdmin.Host/Extensions/MethodInfoExtensions.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace NetAdmin.Host.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Type 扩展方法
|
||||
/// </summary>
|
||||
public static class MethodInfoExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取路由路径
|
||||
/// </summary>
|
||||
public static string GetRoutePath(this MethodInfo me, IServiceProvider serviceProvider)
|
||||
{
|
||||
return serviceProvider.GetService<IActionDescriptorCollectionProvider>()
|
||||
.ActionDescriptors.Items.FirstOrDefault(x => x.DisplayName!.StartsWith( //
|
||||
$"{me.DeclaringType}.{me.Name}"
|
||||
, StringComparison.Ordinal))
|
||||
?.AttributeRouteInfo?.Template;
|
||||
}
|
||||
}
|
@ -108,22 +108,20 @@ public static class ServiceCollectionExtensions
|
||||
return me.AddConsoleFormatter(options => {
|
||||
var logLevels = Enum.GetValues<LogLevels>().ToDictionary(x => x, x => x.GetDisplay());
|
||||
|
||||
#if DEBUG
|
||||
options.WriteHandler = (message, _, _, _, _) => {
|
||||
#if DEBUG
|
||||
MarkupLine(message.Message.EscapeMarkup(), message, logLevels);
|
||||
if (message.Exception != null) {
|
||||
MarkupLine(message.Exception.ToString().EscapeMarkup(), message, logLevels);
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
options.WriteHandler = (message, _, _, _, _) => {
|
||||
#else
|
||||
var msg = message.Message.ReplaceLineEndings(string.Empty);
|
||||
var (date, logName, logFormat) = ParseMessage(message, false);
|
||||
Console.WriteLine( //
|
||||
logFormat, date, logLevels[(LogLevels)message.LogLevel].ShortName, logName, message.ThreadId, msg);
|
||||
#endif
|
||||
GlobalStatic.IncrementLogCounter();
|
||||
};
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ public sealed class DefaultApiResultHandler : ApiResultHandler<RestfulInfo<objec
|
||||
/// <inheritdoc />
|
||||
public IActionResult OnAuthorizeException(DefaultHttpContext context, ExceptionMetadata metadata)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
LogHelper.Get<DefaultApiResultHandler>().Error(metadata.Exception);
|
||||
throw metadata.Exception;
|
||||
}
|
||||
}
|
@ -9,36 +9,64 @@ namespace NetAdmin.Host.Middlewares;
|
||||
public sealed class SafetyShopHostMiddleware(RequestDelegate next)
|
||||
{
|
||||
private static long _connections;
|
||||
private static bool _hostStopping;
|
||||
private static bool _trafficOff;
|
||||
|
||||
/// <summary>
|
||||
/// 当前连接数
|
||||
/// </summary>
|
||||
public static long Connections => Interlocked.Read(ref _connections);
|
||||
|
||||
/// <summary>
|
||||
/// 是否已停机
|
||||
/// </summary>
|
||||
public static bool IsShutdown => Volatile.Read(ref _trafficOff);
|
||||
|
||||
/// <summary>
|
||||
/// 停机处理
|
||||
/// </summary>
|
||||
public static void OnStopping()
|
||||
{
|
||||
Volatile.Write(ref _hostStopping, true);
|
||||
Stop();
|
||||
while (Interlocked.Read(ref _connections) > 0) {
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统启机
|
||||
/// </summary>
|
||||
public static void Start()
|
||||
{
|
||||
Volatile.Write(ref _trafficOff, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统停机
|
||||
/// </summary>
|
||||
public static void Stop()
|
||||
{
|
||||
Volatile.Write(ref _trafficOff, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主函数
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
if (Volatile.Read(ref _hostStopping)) {
|
||||
if (Volatile.Read(ref _trafficOff) &&
|
||||
!context.Request.Path.StartsWithSegments($"/{Chars.FLG_PATH_API_RPOBE}")) {
|
||||
context.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
|
||||
return;
|
||||
}
|
||||
|
||||
_ = Interlocked.Increment(ref _connections);
|
||||
await next(context).ConfigureAwait(false);
|
||||
_ = Interlocked.Decrement(ref _connections);
|
||||
// webSocket链接不参与计算
|
||||
if (context.Request.Path.StartsWithSegments($"/{Chars.FLG_PATH_WEBSOCKET_PREFIX}")) {
|
||||
await next(context).ConfigureAwait(false);
|
||||
}
|
||||
else {
|
||||
_ = Interlocked.Increment(ref _connections);
|
||||
await next(context).ConfigureAwait(false);
|
||||
_ = Interlocked.Decrement(ref _connections);
|
||||
}
|
||||
}
|
||||
}
|
@ -73,12 +73,15 @@ public static class Chars
|
||||
public const string FLG_HTTP_METHOD_POST = "POST";
|
||||
public const string FLG_HTTP_METHOD_PUT = "PUT";
|
||||
public const string FLG_HTTP_METHOD_TRACE = "TRACE";
|
||||
public const string FLG_PATH_API_SYS_USER_LOGIN_BY_PWD = "api/sys/user/login.by.pwd";
|
||||
public const string FLG_PATH_PREFIX_HEALTH_CHECK = "probe/health.check";
|
||||
public const string FLG_RANDOM_UNAME_PWD = "VcXlp7WY";
|
||||
public const string FLG_REDIS_INSTANCE_DATA_CACHE = "DataCache";
|
||||
public const string FLG_SNOWFLAKE_WORK_ID = "SNOWFLAKE_WORK_ID";
|
||||
public const string FLG_SYSTEM_PREFIX = "sc_";
|
||||
|
||||
public const string FLG_PATH_API_RPOBE = "api/probe";
|
||||
public const string FLG_PATH_API_SYS_USER_LOGIN_BY_PWD = "api/sys/user/login.by.pwd";
|
||||
public const string FLG_PATH_PREFIX_HEALTH_CHECK = "probe/health.check";
|
||||
public const string FLG_PATH_WEBSOCKET_PREFIX = "ws";
|
||||
public const string FLG_RANDOM_UNAME_PWD = "VcXlp7WY";
|
||||
public const string FLG_REDIS_INSTANCE_DATA_CACHE = "DataCache";
|
||||
public const string FLG_SNOWFLAKE_WORK_ID = "SNOWFLAKE_WORK_ID";
|
||||
public const string FLG_SYSTEM_PREFIX = "sc_";
|
||||
|
||||
public const string FLGL_HTTP_HEADER_VALUE_UA_MOBILE
|
||||
= "Mozilla/5.0 (Linux; Android 9; Redmi Note 8 Pro Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.96 Mobile Safari/537.36";
|
||||
|
@ -7,12 +7,19 @@ namespace NetAdmin.Infrastructure;
|
||||
/// </summary>
|
||||
public static class GlobalStatic
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前进程
|
||||
/// </summary>
|
||||
public static readonly Process CurrentProcess = Process.GetCurrentProcess();
|
||||
|
||||
/// <summary>
|
||||
/// 产品版本
|
||||
/// </summary>
|
||||
public static readonly string ProductVersion
|
||||
= FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly()!.Location).ProductVersion;
|
||||
|
||||
private static long _latestLogTime;
|
||||
|
||||
/// <summary>
|
||||
/// 调试模式
|
||||
/// </summary>
|
||||
@ -24,10 +31,17 @@ public static class GlobalStatic
|
||||
#endif
|
||||
;
|
||||
|
||||
/// <summary>
|
||||
/// 最后一次日志时间
|
||||
/// </summary>
|
||||
public static DateTime LatestLogTime => Volatile.Read(ref _latestLogTime).Time();
|
||||
|
||||
/// <summary>
|
||||
/// 日志记录器忽略的API编号
|
||||
/// </summary>
|
||||
public static string[] LoggerIgnoreApiIds => [];
|
||||
public static string[] LoggerIgnoreApiIds => [
|
||||
"api/adm/tools/query.es.log", "api/probe/health.check", "api/probe/is.system.safety.stopped"
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// 系统内部密钥
|
||||
@ -73,4 +87,12 @@ public static class GlobalStatic
|
||||
/// Json序列化选项
|
||||
/// </summary>
|
||||
public static JsonSerializerOptions JsonSerializerOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 增加日志计数器
|
||||
/// </summary>
|
||||
public static void IncrementLogCounter()
|
||||
{
|
||||
Volatile.Write(ref _latestLogTime, DateTime.Now.TimeUnixUtcMs());
|
||||
}
|
||||
}
|
@ -6,13 +6,13 @@
|
||||
<Import Project="$(SolutionDir)/build/copy.pkg.xml.comment.files.targets"/>
|
||||
<Import Project="$(SolutionDir)/build/prebuild.targets"/>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.833-preview20260627-ns1"/>
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.833-preview20260627-ns1"/>
|
||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.833-ns4"/>
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.833-ns4"/>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.5.2"/>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.5.2-ns1"/>
|
||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.5.2-ns1"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.10.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.6.24328.4"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.7.24406.2"/>
|
||||
<PackageReference Include="Minio" Version="6.0.3"/>
|
||||
<PackageReference Include="NSExt" Version="2.2.0"/>
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4"/>
|
||||
|
@ -18,7 +18,6 @@ public sealed class FreeSqlBuilder(DatabaseOptions databaseOptions)
|
||||
.UseAutoSyncStructure(
|
||||
initMethods.HasFlag(FreeSqlInitMethods.SyncStructure))
|
||||
.Build();
|
||||
|
||||
_ = InitDbAsync(freeSql, initMethods); // 初始化数据库 ,异步
|
||||
return freeSql;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Cache;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
@ -7,11 +8,21 @@ namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
/// </summary>
|
||||
public interface ICacheModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除缓存项
|
||||
/// </summary>
|
||||
Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 缓存统计
|
||||
/// </summary>
|
||||
Task<CacheStatisticsRsp> CacheStatisticsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 删除缓存项
|
||||
/// </summary>
|
||||
Task<int> DeleteEntryAsync(DelEntryReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有缓存项
|
||||
/// </summary>
|
||||
|
@ -7,6 +7,11 @@ namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
/// </summary>
|
||||
public interface IToolsModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行SQL语句
|
||||
/// </summary>
|
||||
Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 获取更新日志
|
||||
/// </summary>
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using NetAdmin.Application.Services;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Cache;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using StackExchange.Redis;
|
||||
@ -21,6 +22,20 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
|
||||
_redisInstance = redisOptions.Value.Instances.First(x => x.Name == Chars.FLG_REDIS_INSTANCE_DATA_CACHE);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = 0;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach (var item in req.Items) {
|
||||
ret += await DeleteEntryAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<CacheStatisticsRsp> CacheStatisticsAsync()
|
||||
{
|
||||
@ -30,6 +45,16 @@ public sealed class CacheService(IConnectionMultiplexer connectionMultiplexer) /
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteEntryAsync(DelEntryReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
#pragma warning disable VSTHRD103
|
||||
var database = connectionMultiplexer.GetDatabase(_redisInstance.Database);
|
||||
var delSuccess = await database.KeyDeleteAsync(req.Key).ConfigureAwait(false);
|
||||
return delSuccess ? 1 : 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<GetEntryRsp>> GetAllEntriesAsync(GetAllEntriesReq req)
|
||||
{
|
||||
|
@ -84,7 +84,9 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) //
|
||||
public async Task<QueryConfigRsp> GetAsync(QueryConfigReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryConfigReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
var ret = await QueryInternal(new QueryReq<QueryConfigReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryConfigRsp>();
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,9 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
|
||||
public async Task<QueryDeptRsp> GetAsync(QueryDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDeptReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
var ret = await QueryInternal(new QueryReq<QueryDeptReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDeptRsp>();
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ public sealed class DicCatalogService(BasicRepository<Sys_DicCatalog, long> rpo)
|
||||
public async Task<QueryDicCatalogRsp> GetAsync(QueryDicCatalogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDicCatalogReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryDicCatalogReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDicCatalogRsp>();
|
||||
|
@ -104,7 +104,7 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
public async Task<QueryDicContentRsp> GetAsync(QueryDicContentReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryDicContentReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryDicContentReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryDicContentRsp>();
|
||||
@ -145,6 +145,9 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
public async Task<List<QueryDicContentRsp>> QueryByCatalogCodeAsync(string catalogCode)
|
||||
{
|
||||
var ret = await Rpo.Orm.Select<Sys_DicContent>()
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Include(a => a.Catalog)
|
||||
.Where(a => a.Catalog.Code == catalogCode)
|
||||
.ToListAsync()
|
||||
|
@ -73,7 +73,7 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
|
||||
public async Task<QueryJobRecordRsp> GetAsync(QueryJobRecordReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryJobRecordReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryJobRecordReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryJobRecordRsp>();
|
||||
|
@ -112,9 +112,11 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
}
|
||||
]
|
||||
};
|
||||
var job = await QueryInternal(new QueryReq<QueryJobReq> { Count = 1, Filter = req, DynamicFilter = df })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false) ?? throw new NetAdminInvalidOperationException(Ln.未获取到待执行任务);
|
||||
var job
|
||||
= await QueryInternal(
|
||||
new QueryReq<QueryJobReq> { Count = 1, Filter = req, DynamicFilter = df, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false) ?? throw new NetAdminInvalidOperationException(Ln.未获取到待执行任务);
|
||||
|
||||
var nextExecTime = GetNextExecTime(Chars.FLG_CRON_PER_SECS);
|
||||
try {
|
||||
@ -175,7 +177,9 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
public async Task<QueryJobRsp> GetAsync(QueryJobReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryJobReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
var ret = await QueryInternal(new QueryReq<QueryJobReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryJobRsp>();
|
||||
}
|
||||
|
||||
@ -201,13 +205,26 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
}
|
||||
]
|
||||
};
|
||||
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Order = Orders.Random })
|
||||
.Take(1)
|
||||
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Order = Orders.Random }, false)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
|
||||
.As("b")
|
||||
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
|
||||
.Any())
|
||||
.ToOneAsync()
|
||||
.ToOneAsync(a => new {
|
||||
a.RequestUrl
|
||||
, a.HttpMethod
|
||||
, a.RequestHeader
|
||||
, a.RequestBody
|
||||
, a.RandomDelayBegin
|
||||
, a.RandomDelayEnd
|
||||
, a.UserId
|
||||
, a.Id
|
||||
, a.NextTimeId
|
||||
, a.Version
|
||||
})
|
||||
.ConfigureAwait(false);
|
||||
if (job == null) {
|
||||
return null;
|
||||
@ -215,15 +232,15 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
|
||||
#if DBTYPE_SQLSERVER
|
||||
var ret = await UpdateReturnListAsync( //
|
||||
job with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
|
||||
, [nameof(job.Status), nameof(job.LastExecTime)])
|
||||
job.Adapt<Sys_Job>() with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
|
||||
, [nameof(Sys_Job.Status), nameof(Sys_Job.LastExecTime)])
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return ret.FirstOrDefault()?.Adapt<QueryJobRsp>();
|
||||
#else
|
||||
return await UpdateAsync( //
|
||||
job with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
|
||||
, [nameof(job.Status), nameof(job.LastExecTime)])
|
||||
job.Adapt<Sys_Job>() with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
|
||||
, [nameof(Sys_Job.Status), nameof(Sys_Job.LastExecTime)])
|
||||
.ConfigureAwait(false) > 0
|
||||
? await GetAsync(new QueryJobReq { Id = job.Id }).ConfigureAwait(false)
|
||||
: null;
|
||||
@ -330,12 +347,21 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
|
||||
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.Include(a => a.User)
|
||||
.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords));
|
||||
return QueryInternal(req, true);
|
||||
}
|
||||
|
||||
private ISelect<Sys_Job> QueryInternal(QueryReq<QueryJobReq> req, bool includeUser)
|
||||
{
|
||||
var ret = Rpo.Select;
|
||||
if (includeUser) {
|
||||
ret = ret.Include(a => a.User);
|
||||
}
|
||||
|
||||
ret = ret.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.JobName.Contains(req.Keywords));
|
||||
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
|
@ -72,7 +72,7 @@ public sealed class LoginLogService(BasicRepository<Sys_LoginLog, long> rpo) //
|
||||
public async Task<QueryLoginLogRsp> GetAsync(QueryLoginLogReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryLoginLogReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryLoginLogReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryLoginLogRsp>();
|
||||
|
@ -88,7 +88,9 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
|
||||
public async Task<QueryMenuRsp> GetAsync(QueryMenuReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryMenuReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
var ret = await QueryInternal(new QueryReq<QueryMenuReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryMenuRsp>();
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public sealed class RequestLogDetailService(BasicRepository<Sys_RequestLogDetail
|
||||
public async Task<QueryRequestLogDetailRsp> GetAsync(QueryRequestLogDetailReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryRequestLogDetailReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryRequestLogDetailReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryRequestLogDetailRsp>();
|
||||
|
@ -99,7 +99,8 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo,
|
||||
}.Json()
|
||||
.Object<JsonElement>()
|
||||
};
|
||||
var ret = await QueryInternal(new QueryReq<QueryRequestLogReq> { Filter = req, DynamicFilter = df })
|
||||
var ret = await QueryInternal(
|
||||
new QueryReq<QueryRequestLogReq> { Filter = req, DynamicFilter = df, Order = Orders.None })
|
||||
.Include(a => a.Detail)
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
@ -96,7 +96,9 @@ public sealed class RoleService(BasicRepository<Sys_Role, long> rpo) //
|
||||
public async Task<QueryRoleRsp> GetAsync(QueryRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryRoleReq> { Filter = req }).ToOneAsync().ConfigureAwait(false);
|
||||
var ret = await QueryInternal(new QueryReq<QueryRoleReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryRoleRsp>();
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public sealed class SiteMsgDeptService(BasicRepository<Sys_SiteMsgDept, long> rp
|
||||
public async Task<QuerySiteMsgDeptRsp> GetAsync(QuerySiteMsgDeptReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgDeptReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgDeptReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgDeptRsp>();
|
||||
|
@ -71,7 +71,7 @@ public sealed class SiteMsgFlagService(BasicRepository<Sys_SiteMsgFlag, long> rp
|
||||
public async Task<QuerySiteMsgFlagRsp> GetAsync(QuerySiteMsgFlagReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgFlagReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgFlagReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgFlagRsp>();
|
||||
|
@ -71,7 +71,7 @@ public sealed class SiteMsgRoleService(BasicRepository<Sys_SiteMsgRole, long> rp
|
||||
public async Task<QuerySiteMsgRoleRsp> GetAsync(QuerySiteMsgRoleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgRoleReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgRoleReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgRoleRsp>();
|
||||
|
@ -120,7 +120,7 @@ public sealed class SiteMsgService(
|
||||
public async Task<QuerySiteMsgRsp> GetAsync(QuerySiteMsgReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgReq> { Filter = req, Order = Orders.None })
|
||||
.IncludeMany(a => a.Roles)
|
||||
.IncludeMany(a => a.Users)
|
||||
.IncludeMany(a => a.Depts)
|
||||
|
@ -71,7 +71,7 @@ public sealed class SiteMsgUserService(BasicRepository<Sys_SiteMsgUser, long> rp
|
||||
public async Task<QuerySiteMsgUserRsp> GetAsync(QuerySiteMsgUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgUserReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QuerySiteMsgUserReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QuerySiteMsgUserRsp>();
|
||||
|
@ -7,6 +7,15 @@ namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
/// <inheritdoc cref="IToolsService" />
|
||||
public sealed class ToolsService : ServiceBase<IToolsService>, IToolsService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req)
|
||||
{
|
||||
return App.GetService<IFreeSql>()
|
||||
.Ado.CommandFluent(req.Sql)
|
||||
.CommandTimeout(req.TimeoutSecs)
|
||||
.ExecuteArrayAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<string> GetChangeLogAsync()
|
||||
{
|
||||
|
@ -100,7 +100,7 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp
|
||||
public async Task<QueryUserProfileRsp> GetAsync(QueryUserProfileReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryUserProfileReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryUserProfileReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryUserProfileRsp>();
|
||||
|
@ -172,9 +172,9 @@ public sealed class UserService(
|
||||
public async Task<QueryUserRsp> GetAsync(QueryUserReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await (await QueryInternalAsync(new QueryReq<QueryUserReq> { Filter = req }).ConfigureAwait(false))
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
var ret = await (await QueryInternalAsync(new QueryReq<QueryUserReq> { Filter = req, Order = Orders.None })
|
||||
.ConfigureAwait(false)).ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryUserRsp>();
|
||||
}
|
||||
|
||||
@ -433,14 +433,51 @@ public sealed class UserService(
|
||||
/// <inheritdoc />
|
||||
public async Task<UserInfoRsp> UserInfoAsync()
|
||||
{
|
||||
static void OtherIncludes(ISelect<Sys_Role> select)
|
||||
{
|
||||
select.Where(a => a.Enabled)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.IncludeMany( //
|
||||
a => a.Menus
|
||||
#if DBTYPE_SQLSERVER
|
||||
#pragma warning disable SA1115
|
||||
, then => then.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#pragma warning restore SA1115
|
||||
#endif
|
||||
#pragma warning disable SA1009, SA1111
|
||||
)
|
||||
#pragma warning restore SA1111, SA1009
|
||||
.IncludeMany( //
|
||||
a => a.Depts
|
||||
#if DBTYPE_SQLSERVER
|
||||
#pragma warning disable SA1115
|
||||
, then => then.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#pragma warning restore SA1115
|
||||
#endif
|
||||
#pragma warning disable SA1009, SA1111
|
||||
)
|
||||
#pragma warning restore SA1111, SA1009
|
||||
.IncludeMany( //
|
||||
a => a.Apis
|
||||
#if DBTYPE_SQLSERVER
|
||||
#pragma warning disable SA1115
|
||||
, then => then.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#pragma warning restore SA1115
|
||||
#endif
|
||||
#pragma warning disable SA1009, SA1111
|
||||
)
|
||||
#pragma warning restore SA1111, SA1009
|
||||
;
|
||||
}
|
||||
|
||||
var dbUser = await Rpo.Where(a => a.Token == UserToken.Token && a.Enabled)
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Include(a => a.Dept)
|
||||
.IncludeMany( //
|
||||
a => a.Roles
|
||||
, then => then.Where(a => a.Enabled)
|
||||
.IncludeMany(a => a.Menus)
|
||||
.IncludeMany(a => a.Depts)
|
||||
.IncludeMany(a => a.Apis))
|
||||
.IncludeMany(a => a.Roles, OtherIncludes)
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return dbUser.Adapt<UserInfoRsp>();
|
||||
|
@ -81,7 +81,7 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
|
||||
public async Task<QueryVerifyCodeRsp> GetAsync(QueryVerifyCodeReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryVerifyCodeReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryVerifyCodeReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryVerifyCodeRsp>();
|
||||
@ -188,11 +188,10 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
|
||||
, Value = destDevice
|
||||
}
|
||||
})
|
||||
#if DBTYPE_SQLSERVER
|
||||
#if DBTYPE_SQLSERVER
|
||||
.WithLock(SqlServerLock.NoLock | SqlServerLock.NoWait)
|
||||
#endif
|
||||
.Take(1)
|
||||
.ToOneAsync();
|
||||
#endif
|
||||
.ToOneAsync();
|
||||
}
|
||||
|
||||
private ISelect<Sys_VerifyCode> QueryInternal(QueryReq<QueryVerifyCodeReq> req)
|
||||
|
@ -73,7 +73,7 @@ public sealed class ExampleService(BasicRepository<Tpl_Example, long> rpo) //
|
||||
public async Task<QueryExampleRsp> GetAsync(QueryExampleReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req })
|
||||
var ret = await QueryInternal(new QueryReq<QueryExampleReq> { Filter = req, Order = Orders.None })
|
||||
.ToOneAsync()
|
||||
.ConfigureAwait(false);
|
||||
return ret.Adapt<QueryExampleRsp>();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using NetAdmin.Cache;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Cache;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
@ -9,6 +10,12 @@ namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
public sealed class CacheCache(IDistributedCache cache, ICacheService service) //
|
||||
: DistributedCache<ICacheService>(cache, service), IScoped, ICacheCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req)
|
||||
{
|
||||
return Service.BulkDeleteEntryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<CacheStatisticsRsp> CacheStatisticsAsync()
|
||||
{
|
||||
@ -20,6 +27,12 @@ public sealed class CacheCache(IDistributedCache cache, ICacheService service) /
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteEntryAsync(DelEntryReq req)
|
||||
{
|
||||
return Service.DeleteEntryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<GetEntryRsp>> GetAllEntriesAsync(GetAllEntriesReq req)
|
||||
{
|
||||
|
@ -9,6 +9,12 @@ namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
public sealed class ToolsCache(IDistributedCache cache, IToolsService service) //
|
||||
: DistributedCache<IToolsService>(cache, service), IScoped, IToolsCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req)
|
||||
{
|
||||
return Service.ExecuteSqlAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<string> GetChangeLogAsync()
|
||||
{
|
||||
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Cache;
|
||||
using NetAdmin.Host.Controllers;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
@ -12,6 +13,14 @@ namespace NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
[ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))]
|
||||
public sealed class CacheController(ICacheCache cache) : ControllerBase<ICacheCache, ICacheService>(cache), ICacheModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除缓存项
|
||||
/// </summary>
|
||||
public Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req)
|
||||
{
|
||||
return Cache.BulkDeleteEntryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存统计
|
||||
/// </summary>
|
||||
@ -20,6 +29,14 @@ public sealed class CacheController(ICacheCache cache) : ControllerBase<ICacheCa
|
||||
return Cache.CacheStatisticsAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除缓存项
|
||||
/// </summary>
|
||||
public Task<int> DeleteEntryAsync(DelEntryReq req)
|
||||
{
|
||||
return Cache.DeleteEntryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有缓存项
|
||||
/// </summary>
|
||||
|
@ -12,6 +12,14 @@ namespace NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
[ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))]
|
||||
public sealed class ToolsController(IToolsCache cache) : ControllerBase<IToolsCache, IToolsService>(cache), IToolsModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行SQL语句
|
||||
/// </summary>
|
||||
public Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req)
|
||||
{
|
||||
return Cache.ExecuteSqlAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取更新日志
|
||||
/// </summary>
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Furion.Schedule;
|
||||
using NetAdmin.Host.BackgroundRunning;
|
||||
using NetAdmin.Host.Middlewares;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Jobs;
|
||||
@ -27,6 +28,11 @@ public sealed class FreeScheduledJob : WorkBase<FreeScheduledJob>, IJob
|
||||
/// <exception cref="NetAdminGetLockerException">加锁失败异常</exception>
|
||||
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
|
||||
{
|
||||
if (SafetyShopHostMiddleware.IsShutdown) {
|
||||
Console.WriteLine(Ln.此节点已下线);
|
||||
return;
|
||||
}
|
||||
|
||||
await WorkflowAsync(true, stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
using NetAdmin.Host.BackgroundRunning;
|
||||
using NetAdmin.Host.Extensions;
|
||||
using NetAdmin.Host.Middlewares;
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Jobs;
|
||||
@ -42,6 +43,11 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
||||
/// <exception cref="NetAdminGetLockerException">加锁失败异常</exception>
|
||||
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
|
||||
{
|
||||
if (SafetyShopHostMiddleware.IsShutdown) {
|
||||
Console.WriteLine(Ln.此节点已下线);
|
||||
return;
|
||||
}
|
||||
|
||||
await WorkflowAsync(stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
using NetAdmin.Domain.Events.Sys;
|
||||
#if !DEBUG
|
||||
using System.Collections.Concurrent;
|
||||
using NetAdmin.Domain.Dto.Sys.RequestLog;
|
||||
|
||||
#else
|
||||
using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
#endif
|
||||
using NetAdmin.Domain.Events.Sys;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Subscribers;
|
||||
|
||||
@ -8,6 +14,10 @@ namespace NetAdmin.SysComponent.Host.Subscribers;
|
||||
/// </summary>
|
||||
public sealed class OperationLogger : IEventSubscriber
|
||||
{
|
||||
#if !DEBUG
|
||||
private static readonly ConcurrentQueue<CreateRequestLogReq> _requestLogs = new();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 保存请求日志到数据库
|
||||
/// </summary>
|
||||
@ -18,7 +28,47 @@ public sealed class OperationLogger : IEventSubscriber
|
||||
return;
|
||||
}
|
||||
|
||||
operationEvent.Data.TruncateStrings();
|
||||
#if DEBUG
|
||||
_ = await App.GetService<IRequestLogService>().CreateAsync(operationEvent.Data).ConfigureAwait(false);
|
||||
#else
|
||||
if (_requestLogs.Count > Numbers.REQUEST_LOG_BUFF_SIZE) {
|
||||
await WriteToDbAsync().ConfigureAwait(false);
|
||||
}
|
||||
else {
|
||||
_requestLogs.Enqueue(operationEvent.Data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
private static async Task WriteToDbAsync()
|
||||
{
|
||||
var inserts = new List<CreateRequestLogReq>(Numbers.REQUEST_LOG_BUFF_SIZE);
|
||||
|
||||
// 批量入库
|
||||
for (var i = 0; i != Numbers.REQUEST_LOG_BUFF_SIZE; ++i) {
|
||||
if (!_requestLogs.TryDequeue(out var log)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inserts.Add(log);
|
||||
}
|
||||
|
||||
// 如果首尾日期不一致,要分别插入不同的日期分表
|
||||
if (inserts[0].CreatedTime.Date != inserts[^1].CreatedTime.Date) {
|
||||
foreach (var dayInserts in inserts.GroupBy(x => x.CreatedTime.Date)) {
|
||||
await App.GetService<IFreeSql>()
|
||||
.Insert<Sys_RequestLog>(dayInserts.Select(x => x))
|
||||
.ExecuteSqlBulkCopyAsync(tableName: $"{nameof(Sys_RequestLog)}_{dayInserts.Key:yyyyMMdd}")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await App.GetService<IFreeSql>()
|
||||
.Insert<Sys_RequestLog>(inserts)
|
||||
.ExecuteSqlBulkCopyAsync(tableName: $"{nameof(Sys_RequestLog)}_{inserts[0].CreatedTime:yyyyMMdd}")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.AdmServer.Tests/NetAdmin.AdmServer.Tests.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
118
src/backend/NetAdmin.SysComponent.Tests/Sys/ApiTests.cs
Normal file
118
src/backend/NetAdmin.SysComponent.Tests/Sys/ApiTests.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Api;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 接口测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class ApiTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IApiModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryApiRsp> CreateAsync(CreateApiReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryApiRsp> GetAsync(QueryApiReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryApiRsp>> PagedQueryAsync(PagedQueryReq<QueryApiReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryApiRsp>> QueryAsync(QueryReq<QueryApiReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task SyncAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
}
|
||||
}
|
69
src/backend/NetAdmin.SysComponent.Tests/Sys/CacheTests.cs
Normal file
69
src/backend/NetAdmin.SysComponent.Tests/Sys/CacheTests.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Cache;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class CacheTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), ICacheModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteEntryAsync(BulkReq<DelEntryReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CacheController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<CacheStatisticsRsp> CacheStatisticsAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CacheController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteEntryAsync(DelEntryReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CacheController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetEntryRsp>> GetAllEntriesAsync(GetAllEntriesReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CacheController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<GetEntryRsp> GetEntryAsync(GetEntriesReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CacheController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
38
src/backend/NetAdmin.SysComponent.Tests/Sys/CaptchaTests.cs
Normal file
38
src/backend/NetAdmin.SysComponent.Tests/Sys/CaptchaTests.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Sys.Captcha;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 人机验证测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class CaptchaTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), ICaptchaModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<GetCaptchaRsp> GetCaptchaImageAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CaptchaController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> VerifyCaptchaAsync(VerifyCaptchaReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(CaptchaController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
139
src/backend/NetAdmin.SysComponent.Tests/Sys/ConfigTests.cs
Normal file
139
src/backend/NetAdmin.SysComponent.Tests/Sys/ConfigTests.cs
Normal file
@ -0,0 +1,139 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Config;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 配置测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class ConfigTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IConfigModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryConfigRsp> CreateAsync(CreateConfigReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryConfigRsp> EditAsync(EditConfigReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryConfigRsp> GetAsync(QueryConfigReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<QueryConfigRsp> GetLatestConfigAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryConfigRsp>> PagedQueryAsync(PagedQueryReq<QueryConfigReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryConfigRsp>> QueryAsync(QueryReq<QueryConfigReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> SetEnabledAsync(SetConfigEnabledReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ConfigController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
55
src/backend/NetAdmin.SysComponent.Tests/Sys/ConstantTests.cs
Normal file
55
src/backend/NetAdmin.SysComponent.Tests/Sys/ConstantTests.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 常量测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
[SuppressMessage("Usage", "xUnit1031:Do not use blocking task operations in test method")]
|
||||
public class ConstantTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IConstantModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public IDictionary<string, string> GetCharsDic()
|
||||
{
|
||||
var rsp = PostJsonAsync(typeof(ConstantController)).GetAwaiter().GetResult();
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public IDictionary<string, Dictionary<string, string[]>> GetEnums()
|
||||
{
|
||||
var rsp = PostJsonAsync(typeof(ConstantController)).GetAwaiter().GetResult();
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public IDictionary<string, string> GetLocalizedStrings()
|
||||
{
|
||||
var rsp = PostJsonAsync(typeof(ConstantController)).GetAwaiter().GetResult();
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public IDictionary<string, long> GetNumbersDic()
|
||||
{
|
||||
var rsp = PostJsonAsync(typeof(ConstantController)).GetAwaiter().GetResult();
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
130
src/backend/NetAdmin.SysComponent.Tests/Sys/DeptTests.cs
Normal file
130
src/backend/NetAdmin.SysComponent.Tests/Sys/DeptTests.cs
Normal file
@ -0,0 +1,130 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Dept;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 部门测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class DeptTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IDeptModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDeptRsp> CreateAsync(CreateDeptReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDeptRsp> EditAsync(EditDeptReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDeptRsp> GetAsync(QueryDeptReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryDeptRsp>> PagedQueryAsync(PagedQueryReq<QueryDeptReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryDeptRsp>> QueryAsync(QueryReq<QueryDeptReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> SetEnabledAsync(SetDeptEnabledReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DeptController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
45
src/backend/NetAdmin.SysComponent.Tests/Sys/DevTests.cs
Normal file
45
src/backend/NetAdmin.SysComponent.Tests/Sys/DevTests.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Sys.Dev;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 开发测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class DevTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IDevModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task GenerateCsCodeAsync(GenerateCsCodeReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DevController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task GenerateIconCodeAsync(GenerateIconCodeReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DevController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task GenerateJsCodeAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DevController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
}
|
||||
}
|
181
src/backend/NetAdmin.SysComponent.Tests/Sys/DicTests.cs
Normal file
181
src/backend/NetAdmin.SysComponent.Tests/Sys/DicTests.cs
Normal file
@ -0,0 +1,181 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Dic.Catalog;
|
||||
using NetAdmin.Domain.Dto.Sys.Dic.Content;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 字典测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class DicTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IDicModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteCatalogAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteContentAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDicCatalogRsp> CreateCatalogAsync(CreateDicCatalogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDicContentRsp> CreateContentAsync(CreateDicContentReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteCatalogAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteContentAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> EditCatalogAsync(EditDicCatalogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDicContentRsp> EditContentAsync(EditDicContentReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportContentAsync(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDicCatalogRsp> GetCatalogAsync(QueryDicCatalogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryDicContentRsp> GetContentAsync(QueryDicContentReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<string> GetDicValueAsync(GetDicValueReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryDicCatalogRsp>> PagedQueryCatalogAsync(PagedQueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryDicContentRsp>> PagedQueryContentAsync(PagedQueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryDicCatalogRsp>> QueryCatalogAsync(QueryReq<QueryDicCatalogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryDicContentRsp>> QueryContentAsync(QueryReq<QueryDicContentReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(DicController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
28
src/backend/NetAdmin.SysComponent.Tests/Sys/FileTests.cs
Normal file
28
src/backend/NetAdmin.SysComponent.Tests/Sys/FileTests.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 文件测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class FileTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IFileModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<string> UploadAsync(IFormFile file)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(FileController), file);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
212
src/backend/NetAdmin.SysComponent.Tests/Sys/JobTests.cs
Normal file
212
src/backend/NetAdmin.SysComponent.Tests/Sys/JobTests.cs
Normal file
@ -0,0 +1,212 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 计划作业测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class JobTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IJobModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountRecordAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryJobRsp> CreateAsync(CreateJobReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryJobRsp> EditAsync(EditJobReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task ExecuteAsync(QueryJobReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportRecordAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryJobRsp> GetAsync(QueryJobReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryJobRecordRsp> GetRecordAsync(QueryJobRecordReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetBarChartRsp>> GetRecordBarChartAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByHttpStatusCodeAsync(
|
||||
QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetPieChartRsp>> GetRecordPieChartByNameAsync(QueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryJobRsp>> PagedQueryAsync(PagedQueryReq<QueryJobReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryJobRecordRsp>> PagedQueryRecordAsync(PagedQueryReq<QueryJobRecordReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryJobRsp>> QueryAsync(QueryReq<QueryJobReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> SetEnabledAsync(SetJobEnabledReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(JobController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
110
src/backend/NetAdmin.SysComponent.Tests/Sys/LoginLogTests.cs
Normal file
110
src/backend/NetAdmin.SysComponent.Tests/Sys/LoginLogTests.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.LoginLog;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 登录日志测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class LoginLogTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), ILoginLogModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryLoginLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryLoginLogRsp> CreateAsync(CreateLoginLogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryLoginLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryLoginLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryLoginLogRsp> GetAsync(QueryLoginLogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryLoginLogRsp>> PagedQueryAsync(PagedQueryReq<QueryLoginLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryLoginLogRsp>> QueryAsync(QueryReq<QueryLoginLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(LoginLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
128
src/backend/NetAdmin.SysComponent.Tests/Sys/MenuTests.cs
Normal file
128
src/backend/NetAdmin.SysComponent.Tests/Sys/MenuTests.cs
Normal file
@ -0,0 +1,128 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Menu;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 菜单测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class MenuTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IMenuModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryMenuRsp> CreateAsync(CreateMenuReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryMenuRsp> EditAsync(EditMenuReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryMenuRsp> GetAsync(QueryMenuReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryMenuRsp>> PagedQueryAsync(PagedQueryReq<QueryMenuReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryMenuRsp>> QueryAsync(QueryReq<QueryMenuReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<IEnumerable<QueryMenuRsp>> UserMenusAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(MenuTests));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
141
src/backend/NetAdmin.SysComponent.Tests/Sys/RequestLogTests.cs
Normal file
141
src/backend/NetAdmin.SysComponent.Tests/Sys/RequestLogTests.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.RequestLog;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 请求日志测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class RequestLogTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IRequestLogModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryRequestLogRsp> CreateAsync(CreateRequestLogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryRequestLogRsp> GetAsync(QueryRequestLogReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetBarChartRsp>> GetBarChartAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetPieChartRsp>> GetPieChartByApiSummaryAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<GetPieChartRsp>> GetPieChartByHttpStatusCodeAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryRequestLogRsp>> PagedQueryAsync(PagedQueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryRequestLogRsp>> QueryAsync(QueryReq<QueryRequestLogReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RequestLogController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
150
src/backend/NetAdmin.SysComponent.Tests/Sys/RoleTests.cs
Normal file
150
src/backend/NetAdmin.SysComponent.Tests/Sys/RoleTests.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.Role;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 角色测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class RoleTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IRoleModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryRoleRsp> CreateAsync(CreateRoleReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryRoleRsp> EditAsync(EditRoleReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryRoleRsp> GetAsync(QueryRoleReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryRoleRsp>> PagedQueryAsync(PagedQueryReq<QueryRoleReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryRoleRsp>> QueryAsync(QueryReq<QueryRoleReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> SetDisplayDashboardAsync(SetDisplayDashboardReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> SetEnabledAsync(SetRoleEnabledReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> SetIgnorePermissionControlAsync(SetIgnorePermissionControlReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(RoleController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
159
src/backend/NetAdmin.SysComponent.Tests/Sys/SiteMsgTests.cs
Normal file
159
src/backend/NetAdmin.SysComponent.Tests/Sys/SiteMsgTests.cs
Normal file
@ -0,0 +1,159 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsg;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsgFlag;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 站内信测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class SiteMsgTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), ISiteMsgModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QuerySiteMsgRsp> CreateAsync(CreateSiteMsgReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QuerySiteMsgRsp> EditAsync(EditSiteMsgReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QuerySiteMsgRsp> GetAsync(QuerySiteMsgReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QuerySiteMsgRsp> GetMineAsync(QuerySiteMsgReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgRsp>> PagedQueryAsync(PagedQueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QuerySiteMsgRsp>> PagedQueryMineAsync(PagedQueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QuerySiteMsgRsp>> QueryAsync(QueryReq<QuerySiteMsgReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task SetSiteMsgStatusAsync(SetUserSiteMsgStatusReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<long> UnreadCountAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(SiteMsgController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
65
src/backend/NetAdmin.SysComponent.Tests/Sys/ToolsTests.cs
Normal file
65
src/backend/NetAdmin.SysComponent.Tests/Sys/ToolsTests.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Sys.Tool;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 工具测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class ToolsTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IToolsModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<object[][]> ExecuteSqlAsync(ExecuteSqlReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ToolsController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<string> GetChangeLogAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ToolsController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<IEnumerable<GetModulesRsp>> GetModulesAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ToolsController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<DateTime> GetServerUtcTimeAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ToolsController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
public async Task<string> GetVersionAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(ToolsController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
309
src/backend/NetAdmin.SysComponent.Tests/Sys/UserTests.cs
Normal file
309
src/backend/NetAdmin.SysComponent.Tests/Sys/UserTests.cs
Normal file
@ -0,0 +1,309 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
using NetAdmin.Domain.Dto.Sys.UserProfile;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using NetAdmin.Tests.Attributes;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 用户测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
[TestCaseOrderer("NetAdmin.Tests.PriorityOrderer", "NetAdmin.Tests")]
|
||||
public class UserTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IUserModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100100)]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.Equal(HttpStatusCode.NotFound, rsp.StatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100200)]
|
||||
public async Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), new CheckMobileAvailableReq { Mobile = "13838381438" });
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100300)]
|
||||
public async Task<bool> CheckUserNameAvailableAsync(CheckUserNameAvailableReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), new CheckUserNameAvailableReq { UserName = "test" });
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100400)]
|
||||
public async Task<long> CountAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100000)]
|
||||
public async Task<QueryUserRsp> CreateAsync(CreateUserReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController)
|
||||
, new CreateUserReq {
|
||||
UserName = "test"
|
||||
, PasswordText = "1234qwer"
|
||||
, RoleIds = [371729946431493]
|
||||
, DeptId = 372119301627909
|
||||
});
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100600)]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100700)]
|
||||
public async Task<QueryUserRsp> EditAsync(EditUserReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController)
|
||||
, new EditUserReq {
|
||||
UserName = "test"
|
||||
, RoleIds = [371729946431493]
|
||||
, DeptId = 372119301627909
|
||||
});
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100800)]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), new QueryReq<QueryUserReq>());
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(100900)]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101000)]
|
||||
public async Task<QueryUserRsp> GetAsync(QueryUserReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
[TestPriority(101100)]
|
||||
public async Task<GetSessionUserAppConfigRsp> GetSessionUserAppConfigAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101200)]
|
||||
public async Task<LoginRsp> LoginByPwdAsync(LoginByPwdReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController)
|
||||
, new LoginByPwdReq { Account = "root", Password = "1234qwer" });
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101300)]
|
||||
public async Task<LoginRsp> LoginBySmsAsync(LoginBySmsReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController)
|
||||
, new LoginBySmsReq { Code = "1234", DestDevice = "13838381438" });
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101400)]
|
||||
public async Task<PagedQueryRsp<QueryUserRsp>> PagedQueryAsync(PagedQueryReq<QueryUserReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101500)]
|
||||
public async Task<IEnumerable<QueryUserRsp>> QueryAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101600)]
|
||||
public async Task<IEnumerable<QueryUserProfileRsp>> QueryProfileAsync(QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101700)]
|
||||
public async Task<UserInfoRsp> RegisterAsync(RegisterUserReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101800)]
|
||||
public async Task<int> ResetPasswordAsync(ResetPasswordReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(101900)]
|
||||
public async Task<UserInfoRsp> SetAvatarAsync(SetAvatarReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(102000)]
|
||||
public async Task<UserInfoRsp> SetEmailAsync(SetEmailReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(102100)]
|
||||
public async Task<int> SetEnabledAsync(SetUserEnabledReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(102200)]
|
||||
public async Task<UserInfoRsp> SetMobileAsync(SetMobileReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(102300)]
|
||||
public async Task<int> SetPasswordAsync(SetPasswordReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
[TestPriority(102400)]
|
||||
public async Task<int> SetSessionUserAppConfigAsync(SetSessionUserAppConfigReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[Fact]
|
||||
[TestPriority(102500)]
|
||||
public async Task<UserInfoRsp> UserInfoAsync()
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController));
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
130
src/backend/NetAdmin.SysComponent.Tests/Sys/VerifyCodeTests.cs
Normal file
130
src/backend/NetAdmin.SysComponent.Tests/Sys/VerifyCodeTests.cs
Normal file
@ -0,0 +1,130 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NetAdmin.AdmServer.Host;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.VerifyCode;
|
||||
using NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
using NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
using NetAdmin.Tests;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Tests.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 验证码测试
|
||||
/// </summary>
|
||||
[SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")]
|
||||
[SuppressMessage("Usage", "xUnit1028:Test method must have valid return type")]
|
||||
public class VerifyCodeTests(WebTestApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
|
||||
: WebApiTestBase<Startup>(factory, testOutputHelper), IVerifyCodeModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<long> CountAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryVerifyCodeRsp> CreateAsync(CreateVerifyCodeReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IActionResult> ExportAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<QueryVerifyCodeRsp> GetAsync(QueryVerifyCodeReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<PagedQueryRsp<QueryVerifyCodeRsp>> PagedQueryAsync(PagedQueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<IEnumerable<QueryVerifyCodeRsp>> QueryAsync(QueryReq<QueryVerifyCodeReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<SendVerifyCodeRsp> SendVerifyCodeAsync(SendVerifyCodeReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(default)]
|
||||
[Theory]
|
||||
public async Task<bool> VerifyAsync(VerifyCodeReq req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(VerifyCodeController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return default;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
namespace NetAdmin.Tests.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// 测试用例优先级
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class TestPriorityAttribute(int priority) : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 优先级
|
||||
/// </summary>
|
||||
public int Priority { get; private set; } = priority;
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0-preview.7.24406.2"/>
|
||||
<PackageReference Include="xunit" Version="2.9.0"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0-preview.6.24328.4"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0-pre.24">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
52
src/backend/NetAdmin.Tests/PriorityOrderer.cs
Normal file
52
src/backend/NetAdmin.Tests/PriorityOrderer.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using NetAdmin.Tests.Attributes;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace NetAdmin.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// 优先级排序
|
||||
/// </summary>
|
||||
public class PriorityOrderer : ITestCaseOrderer
|
||||
{
|
||||
/// <summary>
|
||||
/// 排序测试用例
|
||||
/// </summary>
|
||||
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> testCases)
|
||||
where TTestCase : ITestCase
|
||||
{
|
||||
var sortedMethods = new SortedDictionary<int, List<TTestCase>>();
|
||||
|
||||
foreach (var testCase in testCases) {
|
||||
var priority = 0;
|
||||
|
||||
foreach (var attr in testCase.TestMethod.Method.GetCustomAttributes(
|
||||
typeof(TestPriorityAttribute).AssemblyQualifiedName)) {
|
||||
priority = attr.GetNamedArgument<int>("Priority");
|
||||
}
|
||||
|
||||
GetOrCreate(sortedMethods, priority).Add(testCase);
|
||||
}
|
||||
|
||||
foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority])) {
|
||||
list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(
|
||||
x.TestMethod.Method.Name, y.TestMethod.Method.Name));
|
||||
foreach (var testCase in list) {
|
||||
yield return testCase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TValue GetOrCreate<TKey, TValue>(SortedDictionary<TKey, TValue> dictionary, TKey key)
|
||||
where TValue : new()
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = new TValue();
|
||||
dictionary[key] = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using NetAdmin.Domain.Dto;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
using NetAdmin.Host.Extensions;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
@ -11,34 +12,68 @@ namespace NetAdmin.Tests;
|
||||
/// <summary>
|
||||
/// WebApi 测试用例基类
|
||||
/// </summary>
|
||||
public abstract class WebApiTestBase<T>(WebApplicationFactory<T> factory, ITestOutputHelper testOutputHelper)
|
||||
: IClassFixture<WebApplicationFactory<T>>
|
||||
public abstract class WebApiTestBase<T>(WebTestApplicationFactory<T> factory, ITestOutputHelper testOutputHelper)
|
||||
: IClassFixture<WebTestApplicationFactory<T>>
|
||||
where T : AppStartup
|
||||
{
|
||||
private const string _ACCOUNT = "root";
|
||||
private const string _PASSWORD = "1234qwer";
|
||||
private string _accessToken;
|
||||
// ReSharper disable once StaticMemberInGenericType
|
||||
private static string _accessToken;
|
||||
|
||||
/// <summary>
|
||||
/// Post请求
|
||||
/// </summary>
|
||||
protected async Task<HttpResponseMessage> PostAsync(string url, HttpContent content)
|
||||
protected async Task<HttpResponseMessage> PostAsync(Type type, HttpContent content
|
||||
, [CallerMemberName] string memberName = null)
|
||||
{
|
||||
var client = factory.CreateClient();
|
||||
await Authorization(client);
|
||||
|
||||
var ret = await client.PostAsync(type.GetMethod(memberName!).GetRoutePath(factory.Services), content)
|
||||
.ConfigureAwait(false);
|
||||
testOutputHelper.WriteLine(await ret.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post请求
|
||||
/// </summary>
|
||||
protected async Task<HttpResponseMessage> PostJsonAsync<TRequest>(Type type, TRequest req = default
|
||||
, [CallerMemberName] string memberName = null)
|
||||
{
|
||||
return await PostAsync(type, req == null ? JsonContent.Create(new { }) : JsonContent.Create(req), memberName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post请求
|
||||
/// </summary>
|
||||
protected async Task<HttpResponseMessage> PostJsonAsync(Type type, [CallerMemberName] string memberName = null)
|
||||
{
|
||||
return await PostJsonAsync<object>(type, null, memberName);
|
||||
}
|
||||
|
||||
private static async Task Authorization(HttpClient client)
|
||||
{
|
||||
if (_accessToken == null) {
|
||||
var loginRsp = await client.PostAsync(Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD
|
||||
, JsonContent.Create(
|
||||
new LoginByPwdReq { Password = _PASSWORD, Account = _ACCOUNT }))
|
||||
.ConfigureAwait(false);
|
||||
var loginRspObj = (await loginRsp.Content.ReadAsStringAsync().ConfigureAwait(false))
|
||||
var req = new LoginByPwdReq //
|
||||
{
|
||||
Password
|
||||
= Environment.GetEnvironmentVariable(
|
||||
nameof(WebTestApplicationFactory<T>.TEST_PASSWORD)) ??
|
||||
WebTestApplicationFactory<T>.TEST_PASSWORD
|
||||
, Account
|
||||
= Environment.GetEnvironmentVariable(nameof(WebTestApplicationFactory<T>.TEST_ACCOUNT)) ??
|
||||
WebTestApplicationFactory<T>.TEST_ACCOUNT
|
||||
};
|
||||
var loginAccount = JsonContent.Create(req);
|
||||
var rspMsg = await client.PostAsync( //
|
||||
Chars.FLG_PATH_API_SYS_USER_LOGIN_BY_PWD, loginAccount)
|
||||
.ConfigureAwait(false);
|
||||
var rspObj = (await rspMsg.Content.ReadAsStringAsync().ConfigureAwait(false))
|
||||
.ToObject<RestfulInfo<LoginRsp>>();
|
||||
_accessToken = loginRspObj.Data.AccessToken;
|
||||
_accessToken = rspObj.Data.AccessToken;
|
||||
}
|
||||
|
||||
client.DefaultRequestHeaders.Authorization
|
||||
= new AuthenticationHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA, _accessToken);
|
||||
var ret = await client.PostAsync(url, content).ConfigureAwait(false);
|
||||
testOutputHelper.WriteLine(await ret.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
return ret;
|
||||
}
|
||||
}
|
21
src/backend/NetAdmin.Tests/WebTestApplicationFactory.cs
Normal file
21
src/backend/NetAdmin.Tests/WebTestApplicationFactory.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
|
||||
namespace NetAdmin.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Web 测试应用程序工厂
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class WebTestApplicationFactory<T> : WebApplicationFactory<T>
|
||||
where T : class
|
||||
{
|
||||
/// <summary>
|
||||
/// 测试用户
|
||||
/// </summary>
|
||||
public const string TEST_ACCOUNT = "root";
|
||||
|
||||
/// <summary>
|
||||
/// 测试密码
|
||||
/// </summary>
|
||||
public const string TEST_PASSWORD = "1234qwer";
|
||||
}
|
@ -10,15 +10,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"ace-builds": "^1.35.4",
|
||||
"aieditor": "^1.0.13",
|
||||
"axios": "^1.7.3",
|
||||
"ace-builds": "^1.36.0",
|
||||
"aieditor": "^1.0.14",
|
||||
"axios": "^1.7.5",
|
||||
"clipboard": "^2.0.11",
|
||||
"core-js": "^3.38.0",
|
||||
"core-js": "^3.38.1",
|
||||
"cropperjs": "^1.6.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"echarts": "^5.5.1",
|
||||
"element-plus": "^2.8.0",
|
||||
"element-plus": "^2.8.1",
|
||||
"json-bigint": "^1.0.0",
|
||||
"json5-to-table": "^0.1.8",
|
||||
"markdown-it": "^14.1.0",
|
||||
@ -28,8 +28,8 @@
|
||||
"qrcodejs2": "^0.0.2",
|
||||
"sortablejs": "^1.15.2",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"vue": "^3.4.37",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue": "^3.4.38",
|
||||
"vue-i18n": "^9.14.0",
|
||||
"vue-router": "^4.4.3",
|
||||
"vue3-ace-editor": "^2.2.4",
|
||||
"vue3-json-viewer": "^2.2.2",
|
||||
@ -41,8 +41,8 @@
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-organize-attributes": "^1.0.0",
|
||||
"sass": "^1.77.8",
|
||||
"terser": "^5.31.5",
|
||||
"vite": "^5.4.0"
|
||||
"terser": "^5.31.6",
|
||||
"vite": "^5.4.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
@ -15,4 +15,15 @@ export default {
|
||||
return await http.get(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 系统是否已经安全停止
|
||||
*/
|
||||
isSystemSafetyStopped: {
|
||||
url: `${config.API_URL}/api/probe/is.system.safety.stopped`,
|
||||
name: `系统是否已经安全停止`,
|
||||
get: async function (data = {}, config = {}) {
|
||||
return await http.get(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
@ -5,6 +5,17 @@
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 批量删除缓存项
|
||||
*/
|
||||
bulkDeleteEntry: {
|
||||
url: `${config.API_URL}/api/sys/cache/bulk.delete.entry`,
|
||||
name: `批量删除缓存项`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 缓存统计
|
||||
*/
|
||||
@ -16,6 +27,17 @@ export default {
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除缓存项
|
||||
*/
|
||||
deleteEntry: {
|
||||
url: `${config.API_URL}/api/sys/cache/delete.entry`,
|
||||
name: `删除缓存项`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取所有缓存项
|
||||
*/
|
||||
|
@ -5,6 +5,17 @@
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 执行SQL语句
|
||||
*/
|
||||
executeSql: {
|
||||
url: `${config.API_URL}/api/sys/tools/execute.sql`,
|
||||
name: `执行SQL语句`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取更新日志
|
||||
*/
|
||||
@ -48,4 +59,15 @@ export default {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 系统停机
|
||||
*/
|
||||
shutdown: {
|
||||
url: `${config.API_URL}/api/sys/tools/shutdown`,
|
||||
name: `系统停机`,
|
||||
get: async function (data = {}, config = {}) {
|
||||
return await http.get(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
@ -7,6 +7,29 @@ const T = {
|
||||
top: '40',
|
||||
containLabel: true,
|
||||
},
|
||||
pie: {
|
||||
label: {
|
||||
color: '#999',
|
||||
},
|
||||
},
|
||||
gauge: {
|
||||
axisTick: {
|
||||
lineStyle: {
|
||||
color: '#999',
|
||||
},
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#999',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#999',
|
||||
},
|
||||
title: {
|
||||
color: '#999',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
textStyle: {
|
||||
color: '#999',
|
||||
|
@ -167,7 +167,7 @@ export default {
|
||||
}
|
||||
|
||||
[data-theme='dark'] .sc-filter-my-list li {
|
||||
color: #d0d0d0;
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .sc-filter-my-list li:hover {
|
||||
|
@ -88,6 +88,6 @@ export default {
|
||||
}
|
||||
|
||||
[data-theme='dark'] .sc-page-header__title h2 {
|
||||
color: #d0d0d0;
|
||||
color: #c0c0c0;
|
||||
}
|
||||
</style>
|
@ -100,6 +100,6 @@ export default {
|
||||
}
|
||||
|
||||
.dark .sc-statistic-content {
|
||||
color: #d0d0d0;
|
||||
color: #c0c0c0;
|
||||
}
|
||||
</style>
|
@ -490,7 +490,7 @@ export default {
|
||||
this.loading = true
|
||||
try {
|
||||
await this.exportApi.post(this.getQueryParams())
|
||||
this.$message.success(`数据已导出(上限1万条)`)
|
||||
this.$message.success(`数据已导出(上限2万条)`)
|
||||
} catch {}
|
||||
this.loading = false
|
||||
},
|
||||
|
@ -571,4 +571,20 @@ textarea {
|
||||
color: var(--el-color-info-light-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sc-statistic-error a {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
color: var(--el-color-danger) !important;
|
||||
|
||||
&:after {
|
||||
border-bottom: 1px solid var(--el-color-danger) !important;
|
||||
bottom: 0;
|
||||
content: '';
|
||||
height: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
}
|
@ -108,4 +108,8 @@ html.dark {
|
||||
.ace_gutter {
|
||||
background: var(--el-bg-color-overlay);
|
||||
}
|
||||
|
||||
.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
|
||||
--el-table-row-hover-bg-color: unset;
|
||||
}
|
||||
}
|
@ -302,4 +302,8 @@
|
||||
|
||||
.el-descriptions__body .el-descriptions__table .el-descriptions__cell {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
|
||||
--el-table-row-hover-bg-color: #fffaf0;
|
||||
}
|
59
src/frontend/admin/src/views/sys/cache/index.vue
vendored
59
src/frontend/admin/src/views/sys/cache/index.vue
vendored
@ -62,10 +62,24 @@
|
||||
</el-button-group>
|
||||
</form>
|
||||
</div>
|
||||
<div class="right-panel"></div>
|
||||
<div class="right-panel">
|
||||
<el-button :disabled="selection.length === 0" @click="batchDel" icon="el-icon-delete" plain type="danger"></el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main v-loading="loading" class="nopadding">
|
||||
<sc-table v-if="tableData.length > 0" :data="tableData" :page-size="100" hide-refresh pagination-layout="total" stripe>
|
||||
<sc-table
|
||||
v-if="tableData.length > 0"
|
||||
:data="tableData"
|
||||
:page-size="100"
|
||||
@selection-change="
|
||||
(items) => {
|
||||
selection = items
|
||||
}
|
||||
"
|
||||
hide-refresh
|
||||
pagination-layout="total"
|
||||
stripe>
|
||||
<el-table-column type="selection" />
|
||||
<el-table-column :label="$t('键名')" prop="key" />
|
||||
<el-table-column :label="$t('数据类型')" align="center" prop="type" width="100" />
|
||||
<el-table-column :label="$t('过期时间')" align="right" prop="expireTime" width="200" />
|
||||
@ -73,7 +87,14 @@
|
||||
:buttons="[
|
||||
{
|
||||
icon: 'el-icon-view',
|
||||
click: rowClick,
|
||||
click: viewClick,
|
||||
},
|
||||
{
|
||||
icon: 'el-icon-delete',
|
||||
type: 'danger',
|
||||
confirm: true,
|
||||
title: '删除缓存',
|
||||
click: delClick,
|
||||
},
|
||||
]"
|
||||
:vue="this"
|
||||
@ -94,6 +115,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selection: [],
|
||||
loading: true,
|
||||
dialog: {
|
||||
info: false,
|
||||
@ -113,6 +135,24 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//批量删除
|
||||
async batchDel() {
|
||||
let loading
|
||||
try {
|
||||
await this.$confirm(`确定删除选中的 ${this.selection.length} 项吗?`, '提示', {
|
||||
type: 'warning',
|
||||
})
|
||||
loading = this.$loading()
|
||||
const res = await this.$API.sys_cache.bulkDeleteEntry.post({
|
||||
items: this.selection,
|
||||
})
|
||||
this.$message.success(`删除 ${res.data} 项`)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
await this.getData()
|
||||
loading?.close()
|
||||
},
|
||||
reset() {
|
||||
this.query.keywords = ''
|
||||
this.search()
|
||||
@ -120,10 +160,19 @@ export default {
|
||||
search() {
|
||||
this.getData()
|
||||
},
|
||||
async rowClick(row) {
|
||||
async delClick(row) {
|
||||
try {
|
||||
const res = await this.$API.sys_cache.deleteEntry.post({ key: row.key })
|
||||
this.$message.success(`删除 ${res.data} 项`)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
await this.getData()
|
||||
},
|
||||
async viewClick(row) {
|
||||
this.dialog.info = true
|
||||
await this.$nextTick()
|
||||
this.$refs.info.open(
|
||||
await this.$refs.info.open(
|
||||
() => this.$t('缓存详情'),
|
||||
() => this.$API.sys_cache.getEntry.post({ key: row.key }),
|
||||
)
|
||||
|
@ -227,7 +227,7 @@ export default {
|
||||
const apiCrcs = data.data.rows?.map((x) => x.apiPathCrc32)
|
||||
const ips = data.data.rows?.map((x) => x.createdClientIp) ?? []
|
||||
const res = await Promise.all([
|
||||
ownerIds && ownerIds.length > 0
|
||||
ownerIds && ownerIds.length > 0 && this.$GLOBAL.permissions.some((x) => x === '*/*/*' || x === 'sys/log/operation/user')
|
||||
? this.$API.sys_user.query.post({
|
||||
dynamicFilter: {
|
||||
field: 'id',
|
||||
|
Loading…
x
Reference in New Issue
Block a user