using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using AutoMapper; using NUnit.Framework; using Strata.Analytics.Biz.DbContexts; using Strata.Analytics.Biz.Workbooks.Services; using Strata.Analytics.Models.Utils; using Strata.Analytics.Models.Workbooks; using Strata.Analytics.Test.Unit.Biz.TestData; using Strata.CoreLib.Claims; using Strata.CoreLib.Claims.Extensions; using Strata.Testing.Categories; namespace Strata.Analytics.Test.Unit.Biz.Workbooks { [Category(TestCategory.Unit)] [Parallelizable(ParallelScope.Self)] public class WorkbookCrudTests { private IClaimsPrincipalAccessor _claimsPrincipalAccessor; private AnalyticsDbContext _dbContext; private IMapper _mapper; private WorkbookService _workbookService; [OneTimeSetUp] public void OneTimeSetup() { _claimsPrincipalAccessor = IClaimsPrincipalAccessorMock.GetClaimsPrincipalAccessor(); _dbContext = AnalyticsDbContextMock.GetAnalyticsDbContext(_claimsPrincipalAccessor); _mapper = AutoMapperMock.GetAutoMapper(); _workbookService = new WorkbookService(_dbContext, _claimsPrincipalAccessor, _mapper); _dbContext.Workbooks.AddRange(WorkbookTestData.Workbooks()); _dbContext.Worksheets.AddRange(WorkbookTestData.Worksheets()); _dbContext.SaveChanges(); } [OneTimeTearDown] public async Task OneTimeTearDown() { await _dbContext.Database.EnsureDeletedAsync(); } [Test, Order(1)] public async Task CanCreateWorkbook() { // arrange var workbookCreateInfo = new WorkbookCreateInfo { Name = "New", Description = "This is a New Workbook", DefaultDataSourceId = 1001 }; // act var result = await _workbookService.CreateAsync(workbookCreateInfo, CancellationToken.None); // assert Assert.IsNotNull(result); Assert.That(result.WorkbookId, Is.GreaterThan(WorkbookTestData.Workbooks().Max(wb => wb.WorkbookId))); Assert.That(result.Name, Is.EqualTo(workbookCreateInfo.Name)); Assert.That(result.Description, Is.EqualTo(workbookCreateInfo.Description)); Assert.That(result.DefaultDataSourceId, Is.EqualTo(workbookCreateInfo.DefaultDataSourceId)); Assert.That(result.CreatedByUserGuid, Is.EqualTo(_claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid())); Assert.That(result.UpdatedByUserGuid, Is.EqualTo(_claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid())); Assert.That(result.Worksheets.Count(), Is.EqualTo(0)); } [Test, Order(1)] public async Task CanCreateWorkbookWithSheets() { var newWorksheets = new List(); var worksheet1 = new WorksheetSaveInfo { Name = "New Worksheet", SortOrder = 3, WorksheetType = WorksheetType.Adhoc, Content = JsonDocument.Parse("{\"MyContent\": \"stuff goes here\"}") }; var worksheet2 = new WorksheetSaveInfo { Name = "New Worksheet2", SortOrder = 4, WorksheetType = WorksheetType.Dashboard, Content = JsonDocument.Parse("{\"MyContent\": \"stuff2 goes here\"}") }; newWorksheets.Add(worksheet1); newWorksheets.Add(worksheet2); // arrange var workbookCreateInfo = new WorkbookCreateInfo { Name = "New", Description = "This is a New Workbook", DefaultDataSourceId = 1001, Worksheets = newWorksheets }; // act var result = await _workbookService.CreateAsync(workbookCreateInfo, CancellationToken.None); // assert Assert.IsNotNull(result); Assert.That(result.WorkbookId, Is.GreaterThan(WorkbookTestData.Workbooks().Max(wb => wb.WorkbookId))); Assert.That(result.Name, Is.EqualTo(workbookCreateInfo.Name)); Assert.That(result.Description, Is.EqualTo(workbookCreateInfo.Description)); Assert.That(result.DefaultDataSourceId, Is.EqualTo(workbookCreateInfo.DefaultDataSourceId)); Assert.That(result.CreatedByUserGuid, Is.EqualTo(_claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid())); Assert.That(result.UpdatedByUserGuid, Is.EqualTo(_claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid())); Assert.That(result.Worksheets.Count(), Is.EqualTo(2)); } [Test, Order(1)] public async Task CanUpdateWorkbook() { // arrange var workbookId = _dbContext.Workbooks.First().WorkbookId; await _workbookService.SaveRoleAssignmentsAsync(workbookId, new Batch { Updates = new WorkbookRoleAssignmentSaveInfo[] { new() { IdentityGuid = _claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid(), Role = WorkbookRole.Editor } } }, CancellationToken.None); var workbook = await _workbookService.GetByIdAsync(workbookId, CancellationToken.None); var workbookSaveInfo = new WorkbookSaveInfo(); _mapper.Map(workbook, workbookSaveInfo); var updatedWorksheet = workbook.Worksheets[1]; updatedWorksheet.Name = "Updated WS Name"; updatedWorksheet.Content = JsonDocument.Parse("{\"MyContent\": \"updated content here\"}"); var newWorksheet = new WorksheetSaveInfo { Name = "New Worksheet", SortOrder = 3, WorksheetType = WorksheetType.Adhoc, Content = JsonDocument.Parse("{\"MyContent\": \"stuff goes here\"}") }; var batch = new Batch { Updates = new List { _mapper.Map(updatedWorksheet), newWorksheet }, Deletes = new List { workbook.Worksheets[0].WorksheetId } }; workbookSaveInfo.WorksheetBatch = batch; _dbContext.ChangeTracker.Clear(); // act var result = await _workbookService.UpdateAsync(workbook.WorkbookId, workbookSaveInfo, CancellationToken.None); // assert Assert.IsNotNull(result); Assert.That(result.WorkbookId, Is.EqualTo(workbook.WorkbookId)); Assert.That(result.Name, Is.EqualTo(workbookSaveInfo.Name)); Assert.That(result.Description, Is.EqualTo(workbookSaveInfo.Description)); Assert.That(result.DefaultDataSourceId, Is.EqualTo(workbookSaveInfo.DefaultDataSourceId)); Assert.That(result.CreatedByUserGuid, Is.EqualTo(workbook.CreatedByUserGuid)); Assert.That(result.UpdatedByUserGuid, Is.EqualTo(_claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid())); Assert.That(result.CreatedDate, Is.EqualTo(workbook.CreatedDate)); Assert.That(result.UpdatedDate, Is.EqualTo(DateTimeOffset.UtcNow).Within(500).Milliseconds); // this could fail in debug Assert.Multiple(() => { foreach (var worksheetId in workbookSaveInfo.WorksheetBatch.Deletes) { var resultWorksheet = result.Worksheets.FirstOrDefault(ws => ws.WorksheetId == worksheetId); Assert.That(resultWorksheet, Is.Null); } foreach (var worksheetSaveInfo in workbookSaveInfo.WorksheetBatch.Updates) { // get the worksheet - if it was added, grab the last var resultWorksheet = worksheetSaveInfo.WorksheetId.HasValue ? result.Worksheets.FirstOrDefault(ws => ws.WorksheetId == worksheetSaveInfo.WorksheetId) : result.Worksheets.LastOrDefault(); var expectedCreatedBy = worksheetSaveInfo.WorksheetId.HasValue ? workbook.Worksheets.First(ws => ws.WorksheetId == worksheetSaveInfo.WorksheetId) .CreatedByUserGuid : _claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid(); var expectedUpdateBy = !worksheetSaveInfo.WorksheetId.HasValue || worksheetSaveInfo.WorksheetId == updatedWorksheet.WorksheetId ? _claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid() : workbook.Worksheets .First(ws => ws.WorksheetId == worksheetSaveInfo.WorksheetId) .UpdatedByUserGuid; Assert.That(resultWorksheet.WorkbookId, Is.EqualTo(workbook.WorkbookId)); Assert.That(resultWorksheet.Name, Is.EqualTo(worksheetSaveInfo.Name)); Assert.That(AnalyticsDbContextJsonSafe.JsonDocumentToString(resultWorksheet.Content), Is.EqualTo(AnalyticsDbContextJsonSafe.JsonDocumentToString(worksheetSaveInfo.Content))); Assert.That(resultWorksheet.SortOrder, Is.EqualTo(worksheetSaveInfo.SortOrder)); Assert.That(resultWorksheet.CreatedByUserGuid, Is.EqualTo(expectedCreatedBy)); Assert.That(resultWorksheet.UpdatedByUserGuid, Is.EqualTo(expectedUpdateBy)); } }); } [Test, Order(int.MaxValue)] // always run last public async Task CanDeleteWorkbookAndCascadeToChildren() { // arrange var workbookId = _dbContext.Workbooks.First().WorkbookId; await _workbookService.SaveRoleAssignmentsAsync(workbookId, new Batch { Updates = new WorkbookRoleAssignmentSaveInfo[] { new() { IdentityGuid = _claimsPrincipalAccessor.GetCurrentClaimsPrincipal().GetUserGuid(), Role = WorkbookRole.Editor } } }, CancellationToken.None); var workbook = await _workbookService.GetByIdAsync(workbookId, CancellationToken.None); Assert.That(workbook.Worksheets.Count, Is.GreaterThan(0)); await _dbContext.SaveChangesAsync(); _dbContext.ChangeTracker.Clear(); // act await _workbookService.DeleteAsync(workbookId, CancellationToken.None); var deletedWorkbook = _dbContext.Workbooks.Where(wb => wb.WorkbookId == workbook.WorkbookId); var deletedWorksheets = _dbContext.Worksheets.Where(ws => ws.WorkbookId == workbook.WorkbookId); var deletedRoleAssignments = _dbContext.WorkbookRoleAssignments.Where(ra => ra.WorkbookId == workbook.WorkbookId); // assert Assert.That(deletedWorkbook, Is.Empty); Assert.That(deletedWorksheets, Is.Empty); Assert.That(deletedRoleAssignments, Is.Empty); } } }