public async Task ChangeStatus_should_refresh_properties_and_unset_schedule_when_completed() { var dueTime = Instant.MaxValue; await ExecuteCreateAsync(); await ExecuteChangeStatusAsync(Status.Archived, dueTime); var command = new ChangeContentStatus { Status = Status.Archived, StatusJobId = sut.Snapshot.ScheduleJob !.Id }; A.CallTo(() => contentWorkflow.CanMoveToAsync(A <IContentEntity> ._, Status.Draft, Status.Archived, User)) .Returns(true); var result = await PublishAsync(command); result.ShouldBeEquivalent(sut.Snapshot); Assert.Null(sut.Snapshot.ScheduleJob); LastEvents .ShouldHaveSameEvents( CreateContentEvent(new ContentStatusChanged { Status = Status.Archived }) ); A.CallTo(() => scriptEngine.TransformAsync(A <ScriptVars> ._, "<change-script>", ScriptOptions())) .MustHaveHappened(); }
public async Task Should_throw_exception_when_workflow_transition_not_valid() { var context = CreateContext(CreateContent(Status.Draft), normalSchema); A.CallTo(() => contentWorkflow.CanMoveToAsync(((ContentEntity)context.Content), Status.Draft, Status.Archived, context.User)) .Returns(false); await Assert.ThrowsAsync <ValidationException>(() => context.CheckTransitionAsync(Status.Archived)); }
public async Task Should_throw_exception_if_workflow_transition_not_valid() { var operation = Operation(CreateContent(Status.Draft), normalSchema); A.CallTo(() => contentWorkflow.CanMoveToAsync((ContentEntity)operation.Snapshot, Status.Draft, Status.Archived, operation.User)) .Returns(false); await Assert.ThrowsAsync <ValidationException>(() => operation.CheckTransitionAsync(Status.Archived)); }
public async Task CanChangeStatus_should_throw_exception_if_due_date_in_past() { var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published, DueTime = dueTimeInPast, User = user }; A.CallTo(() => contentWorkflow.CanMoveToAsync(content, command.Status, user)) .Returns(true); await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(schema, content, contentWorkflow, command, false), new ValidationError("Due time must be in the future.", "DueTime")); }
public async Task CanChangeStatus_should_throw_exception_if_status_flow_not_valid() { var content = CreateContent(Status.Draft); var command = CreateCommand(new ChangeContentStatus { Status = Status.Published }); A.CallTo(() => workflow.CanMoveToAsync(content, content.Status, command.Status, user)) .Returns(false); await ValidationAssert.ThrowsAsync(() => GuardContent.CanChangeStatus(command, content, workflow, contentRepository, schema), new ValidationError("Cannot change status from Draft to Published.", "Status")); }
public async Task ChangeStatus_should_refresh_properties_and_revert_scheduling_when_invoked_by_scheduler() { await ExecuteCreateAsync(); await ExecuteChangeStatusAsync(Status.Published, Instant.MaxValue); var command = new ChangeContentStatus { Status = Status.Published, JobId = sut.Snapshot.ScheduleJob.Id }; A.CallTo(() => contentWorkflow.CanMoveToAsync(A <IContentEntity> .Ignored, Status.Published, User)) .Returns(false); var result = await sut.ExecuteAsync(CreateContentCommand(command)); result.ShouldBeEquivalent(sut.Snapshot); Assert.Null(sut.Snapshot.ScheduleJob); LastEvents .ShouldHaveSameEvents( CreateContentEvent(new ContentSchedulingCancelled()) ); A.CallTo(() => scriptEngine.Execute(A <ScriptContext> .Ignored, "<change-script>")) .MustNotHaveHappened(); }
public static Task CanChangeStatus(ISchemaEntity schema, ContentState content, IContentWorkflow contentWorkflow, ChangeContentStatus command) { Guard.NotNull(command, nameof(command)); if (schema.SchemaDef.IsSingleton) { if (content.NewVersion == null || command.Status != Status.Published) { throw new DomainException("Singleton content cannot be updated."); } return(Task.CompletedTask); } return(Validate.It(() => "Cannot change status.", async e => { if (!await contentWorkflow.CanMoveToAsync(content, content.EditingStatus, command.Status, command.User)) { e($"Cannot change status from {content.Status} to {command.Status}.", nameof(command.Status)); } if (command.DueTime.HasValue && command.DueTime.Value < SystemClock.Instance.GetCurrentInstant()) { e("Due time must be in the future.", nameof(command.DueTime)); } })); }
public static Task CanChangeStatus(ISchemaEntity schema, ContentState content, IContentWorkflow contentWorkflow, ChangeContentStatus command) { Guard.NotNull(command, nameof(command)); if (schema.SchemaDef.IsSingleton) { if (content.NewVersion == null || command.Status != Status.Published) { throw new DomainException(T.Get("contents.singletonNotChangeable")); } return(Task.CompletedTask); } return(Validate.It(async e => { if (!await contentWorkflow.CanMoveToAsync(content, content.EditingStatus, command.Status, command.User)) { e(T.Get("contents.statusTransitionNotAllowed", new { oldStatus = content.EditingStatus, newStatus = command.Status }), nameof(command.Status)); } if (command.DueTime.HasValue && command.DueTime.Value < SystemClock.Instance.GetCurrentInstant()) { e(T.Get("contents.statusSchedulingNotInFuture"), nameof(command.DueTime)); } })); }
public static Task CanChangeStatus(ISchemaEntity schema, IContentEntity content, IContentWorkflow contentWorkflow, ChangeContentStatus command, bool isChangeConfirm) { Guard.NotNull(command, nameof(command)); if (schema.SchemaDef.IsSingleton && command.Status != Status.Published) { throw new DomainException("Singleton content cannot be changed."); } return(Validate.It(() => "Cannot change status.", async e => { if (isChangeConfirm) { if (!content.IsPending) { e("Content has no changes to publish.", nameof(command.Status)); } } else if (!await contentWorkflow.CanMoveToAsync(content, command.Status, command.User)) { e($"Cannot change status from {content.Status} to {command.Status}.", nameof(command.Status)); } if (command.DueTime.HasValue && command.DueTime.Value < SystemClock.Instance.GetCurrentInstant()) { e("Due time must be in the future.", nameof(command.DueTime)); } })); }
public static async Task CanChangeStatus(ChangeContentStatus command, IContentEntity content, IContentWorkflow contentWorkflow, IContentRepository contentRepository, ISchemaEntity schema) { Guard.NotNull(command, nameof(command)); CheckPermission(content, command, Permissions.AppContentsChangeStatus, Permissions.AppContentsUpsert); var newStatus = command.Status; if (schema.SchemaDef.IsSingleton) { if (content.NewStatus == null || newStatus != Status.Published) { throw new DomainException(T.Get("contents.singletonNotChangeable")); } return; } var oldStatus = content.NewStatus ?? content.Status; if (oldStatus == Status.Published && command.CheckReferrers) { var hasReferrer = await contentRepository.HasReferrersAsync(content.AppId.Id, command.ContentId, SearchScope.Published); if (hasReferrer) { throw new DomainException(T.Get("contents.referenced")); } } await Validate.It(async e => { if (!command.DoNotValidateWorkflow) { if (!await contentWorkflow.CanMoveToAsync(content, oldStatus, newStatus, command.User)) { var values = new { oldStatus, newStatus }; e(T.Get("contents.statusTransitionNotAllowed", values), "Status"); } } else { var info = await contentWorkflow.GetInfoAsync(content, newStatus); if (info == null) { e(T.Get("contents.statusNotValid"), "Status"); } } }); }
public static Task CanChangeStatus(ChangeContentStatus command, IContentEntity content, IContentWorkflow contentWorkflow, IContentRepository contentRepository, ISchemaEntity schema) { Guard.NotNull(command, nameof(command)); CheckPermission(content, command, Permissions.AppContentsChangeStatus); if (schema.SchemaDef.IsSingleton) { if (content.NewStatus == null || command.Status != Status.Published) { throw new DomainException(T.Get("contents.singletonNotChangeable")); } return(Task.CompletedTask); } return(Validate.It(async e => { var status = content.NewStatus ?? content.Status; if (!await contentWorkflow.CanMoveToAsync(content, status, command.Status, command.User)) { var values = new { oldStatus = status, newStatus = command.Status }; e(T.Get("contents.statusTransitionNotAllowed", values), nameof(command.Status)); } if (content.Status == Status.Published && command.CheckReferrers) { var hasReferrer = await contentRepository.HasReferrersAsync(content.AppId.Id, command.ContentId, SearchScope.Published); if (hasReferrer) { throw new DomainException(T.Get("contents.referenced")); } } if (command.DueTime.HasValue && command.DueTime.Value < SystemClock.Instance.GetCurrentInstant()) { e(T.Get("contents.statusSchedulingNotInFuture"), nameof(command.DueTime)); } })); }