87 lines
3.5 KiB
C#
87 lines
3.5 KiB
C#
using CaptchaKit.AspNetCore;
|
|
using CaptchaKit;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using SkiaSharp;
|
|
|
|
namespace Jiaowu.Api.Tests;
|
|
|
|
public sealed class CaptchaKitIntegrationTests
|
|
{
|
|
[Fact]
|
|
public async Task Challenge_is_valid_once_and_the_default_generator_returns_a_png()
|
|
{
|
|
var services = new ServiceCollection();
|
|
services.AddDistributedMemoryCache();
|
|
services.AddCaptchaKit();
|
|
services.AddSingleton<ICaptchaGenerator, KnownGenerator>();
|
|
using var provider = services.BuildServiceProvider();
|
|
var captcha = provider.GetRequiredService<ICaptchaKitService>();
|
|
|
|
var challenge = await captcha.CreateAsync();
|
|
|
|
Assert.Equal("image/png", challenge.ContentType);
|
|
Assert.True(challenge.ImageBytes!.AsSpan().StartsWith(new byte[] { 137, 80, 78, 71 }));
|
|
Assert.True(await captcha.VerifyAsync(challenge.Id, "a1b2"));
|
|
Assert.False(await captcha.VerifyAsync(challenge.Id, "a1b2"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Default_generator_returns_png_bytes()
|
|
{
|
|
var challenge = new SkiaTextCaptchaGenerator().Generate(
|
|
new CaptchaGenerationRequest("test", DateTimeOffset.UtcNow.AddMinutes(1), 5));
|
|
|
|
Assert.Equal("image/png", challenge.Challenge.ContentType);
|
|
Assert.True(challenge.Challenge.ImageBytes!.AsSpan().StartsWith(new byte[] { 137, 80, 78, 71 }));
|
|
}
|
|
|
|
[Fact]
|
|
public void Selection_visual_keeps_the_target_character_visible_above_noise()
|
|
{
|
|
var challenge = new SkiaTextCaptchaGenerator().CreateVisualChallenge(
|
|
new CaptchaGenerationRequest("test", DateTimeOffset.UtcNow.AddMinutes(1), 5),
|
|
"A", "choice-A", CaptchaChallengeType.Selection, "请选择对应字符");
|
|
|
|
using var bitmap = SKBitmap.Decode(challenge.Challenge.ImageBytes!);
|
|
Assert.NotNull(bitmap);
|
|
|
|
var targetPixelCount = 0;
|
|
for (var y = 0; y < bitmap!.Height; y++)
|
|
for (var x = bitmap.Width / 4; x < bitmap.Width * 3 / 4; x++)
|
|
{
|
|
var pixel = bitmap.GetPixel(x, y);
|
|
if (pixel.Red <= 30 && pixel.Green is >= 40 and <= 60 && pixel.Blue is >= 70 and <= 90)
|
|
targetPixelCount++;
|
|
}
|
|
|
|
Assert.True(targetPixelCount > 20, "The target character should be visibly rendered in the image center.");
|
|
}
|
|
|
|
[Fact]
|
|
public void Random_generator_produces_each_enabled_challenge_type()
|
|
{
|
|
var generator = new RandomCaptchaGenerator(new CaptchaKitOptions());
|
|
var types = new HashSet<CaptchaChallengeType>();
|
|
for (var index = 0; index < 100; index++)
|
|
{
|
|
var generated = generator.Generate(new CaptchaGenerationRequest(
|
|
index.ToString(), DateTimeOffset.UtcNow.AddMinutes(1), 5));
|
|
types.Add(generated.Challenge.Type);
|
|
if (generated.Challenge.Type == CaptchaChallengeType.Selection)
|
|
Assert.Contains(generated.Challenge.Choices!, x => x.Id == generated.Answer);
|
|
}
|
|
|
|
Assert.Contains(CaptchaChallengeType.TextImage, types);
|
|
Assert.Contains(CaptchaChallengeType.Selection, types);
|
|
Assert.Contains(CaptchaChallengeType.MathImage, types);
|
|
}
|
|
|
|
private sealed class KnownGenerator : ICaptchaGenerator
|
|
{
|
|
public GeneratedCaptcha Generate(CaptchaGenerationRequest request) => new(
|
|
new CaptchaChallenge(request.Id, CaptchaChallengeType.TextImage, request.ExpiresAt,
|
|
"请输入图中的字符", null, "image/png", new byte[] { 137, 80, 78, 71 }),
|
|
"A1B2");
|
|
}
|
|
}
|