323 lines
8.8 KiB
C#
323 lines
8.8 KiB
C#
namespace Application.Tests.Validators;
|
|
|
|
using Application.Enrollments.Commands;
|
|
using Application.Students.Commands;
|
|
using Domain.Ports.Repositories;
|
|
using FluentAssertions;
|
|
using FluentValidation.TestHelper;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
public class CreateStudentValidatorTests
|
|
{
|
|
private readonly IStudentRepository _studentRepository;
|
|
private readonly CreateStudentValidator _validator;
|
|
|
|
public CreateStudentValidatorTests()
|
|
{
|
|
_studentRepository = Substitute.For<IStudentRepository>();
|
|
_studentRepository.EmailExistsAsync(Arg.Any<string>(), Arg.Any<int?>(), Arg.Any<CancellationToken>())
|
|
.Returns(false);
|
|
_validator = new CreateStudentValidator(_studentRepository);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithValidCommand_ShouldNotHaveErrors()
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand("John Doe", "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldNotHaveAnyValidationErrors();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithEmptyName_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand("", "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithEmptyEmail_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand("John Doe", "");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Email);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithInvalidEmail_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand("John Doe", "invalid-email");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Email);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithExistingEmail_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
_studentRepository.EmailExistsAsync("existing@example.com", null, Arg.Any<CancellationToken>())
|
|
.Returns(true);
|
|
|
|
var command = new CreateStudentCommand("John Doe", "existing@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Email)
|
|
.WithErrorMessage("Email already exists");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithNameTooLong_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var longName = new string('A', 101);
|
|
var command = new CreateStudentCommand(longName, "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithNameTooShort_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand("AB", "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Name)
|
|
.WithErrorMessage("Name must be at least 3 characters");
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("<script>alert('xss')</script>")]
|
|
[InlineData("John<img src=x onerror=alert(1)>")]
|
|
[InlineData("javascript:alert(1)")]
|
|
public async Task Validate_WithDangerousName_ShouldHaveError(string dangerousName)
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand(dangerousName, "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Name);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("John123")]
|
|
[InlineData("John@Doe")]
|
|
[InlineData("John#Doe")]
|
|
public async Task Validate_WithInvalidCharactersInName_ShouldHaveError(string invalidName)
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand(invalidName, "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Name)
|
|
.WithErrorMessage("Name contains invalid characters");
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("María García")]
|
|
[InlineData("José O'Brien")]
|
|
[InlineData("Ana-María López")]
|
|
[InlineData("Dr. Juan Pérez")]
|
|
public async Task Validate_WithValidSpecialCharactersInName_ShouldPass(string validName)
|
|
{
|
|
// Arrange
|
|
var command = new CreateStudentCommand(validName, "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldNotHaveValidationErrorFor(x => x.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithEmailTooLong_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var longEmail = new string('a', 250) + "@example.com";
|
|
var command = new CreateStudentCommand("John Doe", longEmail);
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Email);
|
|
}
|
|
}
|
|
|
|
public class UpdateStudentValidatorTests
|
|
{
|
|
private readonly IStudentRepository _studentRepository;
|
|
private readonly UpdateStudentValidator _validator;
|
|
|
|
public UpdateStudentValidatorTests()
|
|
{
|
|
_studentRepository = Substitute.For<IStudentRepository>();
|
|
_studentRepository.EmailExistsAsync(Arg.Any<string>(), Arg.Any<int?>(), Arg.Any<CancellationToken>())
|
|
.Returns(false);
|
|
_validator = new UpdateStudentValidator(_studentRepository);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithValidCommand_ShouldNotHaveErrors()
|
|
{
|
|
// Arrange
|
|
var command = new UpdateStudentCommand(1, "John Doe", "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldNotHaveAnyValidationErrors();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithInvalidId_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new UpdateStudentCommand(0, "John Doe", "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithNegativeId_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new UpdateStudentCommand(-1, "John Doe", "john@example.com");
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.Id);
|
|
}
|
|
}
|
|
|
|
public class EnrollStudentValidatorTests
|
|
{
|
|
private readonly EnrollStudentValidator _validator;
|
|
|
|
public EnrollStudentValidatorTests()
|
|
{
|
|
_validator = new EnrollStudentValidator();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithValidCommand_ShouldNotHaveErrors()
|
|
{
|
|
// Arrange
|
|
var command = new EnrollStudentCommand(1, 1);
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldNotHaveAnyValidationErrors();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithInvalidStudentId_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new EnrollStudentCommand(0, 1);
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.StudentId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithInvalidSubjectId_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new EnrollStudentCommand(1, 0);
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.SubjectId);
|
|
}
|
|
}
|
|
|
|
public class UnenrollStudentValidatorTests
|
|
{
|
|
private readonly UnenrollStudentValidator _validator;
|
|
|
|
public UnenrollStudentValidatorTests()
|
|
{
|
|
_validator = new UnenrollStudentValidator();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithValidCommand_ShouldNotHaveErrors()
|
|
{
|
|
// Arrange
|
|
var command = new UnenrollStudentCommand(1);
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldNotHaveAnyValidationErrors();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Validate_WithInvalidEnrollmentId_ShouldHaveError()
|
|
{
|
|
// Arrange
|
|
var command = new UnenrollStudentCommand(0);
|
|
|
|
// Act
|
|
var result = await _validator.TestValidateAsync(command);
|
|
|
|
// Assert
|
|
result.ShouldHaveValidationErrorFor(x => x.EnrollmentId);
|
|
}
|
|
}
|