-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathApplicationWorkflowService.LeaseLifecycleTests.cs
More file actions
152 lines (128 loc) · 7.12 KB
/
ApplicationWorkflowService.LeaseLifecycleTests.cs
File metadata and controls
152 lines (128 loc) · 7.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System.Security.Claims;
using System.Threading.Tasks;
using System;
using Aquiis.SimpleStart.Application.Services.Workflows;
using Aquiis.SimpleStart.Core.Entities;
using Aquiis.SimpleStart.Shared.Services;
using Aquiis.SimpleStart.Shared.Components.Account;
using Aquiis.SimpleStart.Core.Constants;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
namespace Aquiis.SimpleStart.Tests;
public class ApplicationWorkflowServiceLeaseLifecycleTests
{
[Fact]
public async Task GenerateAndAcceptLeaseOffer_CreatesLeaseAndTenant_UpdatesProperty()
{
// Arrange - setup SQLite in-memory
var connection = new Microsoft.Data.Sqlite.SqliteConnection("Data Source=:memory:");
connection.Open();
var options = new DbContextOptionsBuilder<SimpleStart.Infrastructure.Data.ApplicationDbContext>()
.UseSqlite(connection)
.Options;
var testUserId = "test-user-id";
var orgId = Guid.NewGuid();
// Mock AuthenticationStateProvider
var claims = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, testUserId) }, "TestAuth"));
var mockAuth = new Mock<AuthenticationStateProvider>();
mockAuth.Setup(a => a.GetAuthenticationStateAsync())
.ReturnsAsync(new AuthenticationState(claims));
var mockUserStore = new Mock<IUserStore<ApplicationUser>>();
var mockUserManager = new Mock<UserManager<ApplicationUser>>(
mockUserStore.Object,
null, null, null, null, null, null, null, null);
var appUser = new ApplicationUser { Id = testUserId, ActiveOrganizationId = orgId };
mockUserManager.Setup(u => u.FindByIdAsync(It.IsAny<string>())).ReturnsAsync(appUser);
var serviceProvider = new Mock<IServiceProvider>();
var userContext = new UserContextService(mockAuth.Object, mockUserManager.Object, serviceProvider.Object);
// Create DbContext and seed data
await using var context = new SimpleStart.Infrastructure.Data.ApplicationDbContext(options);
await context.Database.EnsureCreatedAsync();
var appUserEntity = new ApplicationUser { Id = testUserId, UserName = "testuser", Email = "t@t.com", ActiveOrganizationId = orgId };
context.Users.Add(appUserEntity);
var org = new Organization { Id = orgId, Name = "TestOrg", OwnerId = testUserId, CreatedBy = testUserId, CreatedOn = DateTime.UtcNow };
context.Organizations.Add(org);
var prospect = new ProspectiveTenant { Id = Guid.NewGuid(), OrganizationId = orgId, FirstName = "Lease", LastName = "Tester", Email = "lt@example.com", Phone = "123", Status = ApplicationConstants.ProspectiveStatuses.Lead, CreatedBy = testUserId, CreatedOn = DateTime.UtcNow };
var property = new Property { Id = Guid.NewGuid(), OrganizationId = orgId, Address = "456 Elm", City = "X", State = "ST", ZipCode = "00000", Status = ApplicationConstants.PropertyStatuses.Available, CreatedBy = testUserId, CreatedOn = DateTime.UtcNow, MonthlyRent = 1200m };
context.ProspectiveTenants.Add(prospect);
context.Properties.Add(property);
await context.SaveChangesAsync();
var noteService = new Application.Services.NoteService(context, userContext);
var workflowService = new ApplicationWorkflowService(context, userContext, noteService);
// Submit application
var submissionModel = new ApplicationSubmissionModel
{
ApplicationFee = 25m,
ApplicationFeePaid = true,
ApplicationFeePaymentMethod = "Card",
CurrentAddress = "Addr",
CurrentCity = "C",
CurrentState = "ST",
CurrentZipCode = "00000",
CurrentRent = 1000m,
LandlordName = "L",
LandlordPhone = "P",
EmployerName = "E",
JobTitle = "J",
MonthlyIncome = 2000m,
EmploymentLengthMonths = 12,
Reference1Name = "R1",
Reference1Phone = "111",
Reference1Relationship = "Friend"
};
var submitResult = await workflowService.SubmitApplicationAsync(prospect.Id, property.Id, submissionModel);
Assert.True(submitResult.Success, string.Join(";", submitResult.Errors));
Assert.NotEqual(Guid.Empty, submitResult.Data!.Id);
var application = submitResult.Data!;
// Initiate screening and complete it as Passed
var screeningResult = await workflowService.InitiateScreeningAsync(application.Id, true, true);
Assert.True(screeningResult.Success, string.Join(";", screeningResult.Errors));
Assert.NotEqual(Guid.Empty, screeningResult.Data!.Id);
var completeScreeningResult = await workflowService.CompleteScreeningAsync(application.Id, new ScreeningResultModel
{
BackgroundCheckPassed = true,
CreditCheckPassed = true,
CreditScore = 700,
OverallResult = "Passed",
ResultNotes = "All good"
});
Assert.True(completeScreeningResult.Success, string.Join(";", completeScreeningResult.Errors));
// Approve application
var approveResult = await workflowService.ApproveApplicationAsync(application.Id);
Assert.True(approveResult.Success, string.Join(";", approveResult.Errors));
// Generate lease offer
var offerModel = new LeaseOfferModel
{
StartDate = DateTime.Today.AddDays(14),
EndDate = DateTime.Today.AddYears(1).AddDays(14),
MonthlyRent = property.MonthlyRent,
SecurityDeposit = property.MonthlyRent,
Terms = "Standard",
Notes = "Test offer"
};
var generateResult = await workflowService.GenerateLeaseOfferAsync(application.Id, offerModel);
Assert.True(generateResult.Success, string.Join(";", generateResult.Errors));
var leaseOffer = generateResult.Data!;
Assert.NotEqual(Guid.Empty, leaseOffer.Id);
// Accept lease offer
var acceptResult = await workflowService.AcceptLeaseOfferAsync(leaseOffer.Id, "Card", DateTime.UtcNow);
Assert.True(acceptResult.Success, string.Join(";", acceptResult.Errors));
var lease = acceptResult.Data!;
// Assert: Lease exists in DB, Tenant created, Property status Occupied
var dbLease = await context.Leases.Include(l => l.Tenant).FirstOrDefaultAsync(l => l.Id == lease.Id);
Assert.NotNull(dbLease);
Assert.NotEqual(Guid.Empty, dbLease.Id);
Assert.NotNull(dbLease!.Tenant);
var dbProperty = await context.Properties.FirstOrDefaultAsync(p => p.Id == property.Id);
Assert.NotNull(dbProperty);
Assert.NotEqual(Guid.Empty, dbProperty.Id);
Assert.Equal(ApplicationConstants.PropertyStatuses.Occupied, dbProperty!.Status);
// Audit logs should contain LeaseOffer Accept entry
var audit = await context.WorkflowAuditLogs.FirstOrDefaultAsync(w => w.EntityType == "LeaseOffer" && w.EntityId == leaseOffer.Id);
Assert.NotNull(audit);
}
}