Пример #1
0
        static string CreateActionLink(DisplayFormUserTask task)
        {
            var    baseAddress = ConfigurationSettings.GetSiteConfigurationSection().SiteSettings.Address;
            var    tenantID    = RequestContext.TenantId;
            string tenantName;

            using (new AdministratorContext())
            {
                tenantName = Entity.Get <Tenant>(tenantID, Tenant.Name_Field).Name;
            }

            string url;

            if (task.RecordToPresent != null)
            {
                url = string.Format(ActionLinkWithRecordFormat, baseAddress, tenantName, task.RecordToPresent.Id, task.Id);
            }
            else
            {
                url = string.Format(ActionLinkFormat, baseAddress, tenantName, task.Id);
            }

            if (task.FormToUse != null)
            {
                url += "&formId=" + task.FormToUse.Id;
            }

            return(url);
        }
Пример #2
0
        private void ActOnTask(DisplayFormUserTask task, TransitionStart userResponse, List <Action> actions)
        {
            //TODO: Serialize the workflow runs like the trigger on save.
            var workflowRun = task.WorkflowRunForTask;

            if ((task.UserTaskIsComplete ?? false) && (workflowRun != null) && (workflowRun.WorkflowRunStatus_Enum == WorkflowRunState_Enumeration.WorkflowRunPaused))
            {
                var resumeEvent = new UserCompletesTaskEvent
                {
                    CompletionStateId = userResponse.Id,
                    UserTaskId        = task.Id
                };

                var    runId       = workflowRun.Id;
                var    runInThread = WorkflowRunContext.Current.RunTriggersInCurrentThread;
                Action act;

                if (Factory.FeatureSwitch.Get("longRunningWorkflow"))
                {
                    act = () => ActionOnTask_new(runId, resumeEvent, runInThread);
                }
                else
                {
                    act = () => ActionOnTask_old(runId, resumeEvent, runInThread);
                }

                WorkflowRunContext.Current.DeferAction(act);
            }
        }
Пример #3
0
        // [Ignore("Failing on first run in test environment.")]
        public void TestWorkflowRunOnReverseRelationshipUpdate()
        {
            using (new WorkflowRunContext {
                RunTriggersInCurrentThread = true
            })
            {
                var ageField = GetPersonField("Age");
                var titleRel = GetTitleRel();

                var myType = CreateMyType("Type_TestWorkflowRunOnUpdate");

                Workflow wf = CreateTestWorkflow("TestWorkflowRunOnRelationshipUpdate " + DateTime.Now, "990");

                var updateTrigger = new WfTriggerUserUpdatesResource
                {
                    WorkflowToRun = wf,
                    // ReSharper disable SpecifyACultureInStringConversionExplicitly
                    Name = "Test" + DateTime.Now.ToString(),
                    // ReSharper restore SpecifyACultureInStringConversionExplicitly
                    TriggeringCondition_Enum = TriggeredOnEnum_Enumeration.TriggeredOnEnumUpdate,
                    TriggerEnabled           = true
                };

                var task = new DisplayFormUserTask();

                var relToUpdate = Entity.Get <Relationship>("core:recordToPresent");
                updateTrigger.UpdatedRelationshipsToTriggerOn.Add(relToUpdate);         // a reverse relationship
                updateTrigger.TriggeredOnType = myType;

                updateTrigger.Save();
                ToDelete.Add(updateTrigger.Id);
                ToDelete.Add(wf.Id);

                EntityRef employee = CreateResource(myType);

                var savedEmployee = Entity.Get(employee);
                var age           = savedEmployee.GetField <int?>(ageField);
                Assert.AreEqual(null, age, "Age has been not been set by workflow");

                var rels = savedEmployee.GetRelationships(relToUpdate);

                rels.Add(task);

                using (new WorkflowRunContext(true))
                    using (var ctx = DatabaseContext.GetContext(true, preventPostSaveActionsPropagating: true))
                    {
                        savedEmployee.Save();

                        ctx.CommitTransaction();
                    }

                savedEmployee = Entity.Get(employee);
                var age1 = savedEmployee.GetField <int?>(ageField);
                Assert.That(age1, Is.EqualTo(990), "The update has not occurred and has not triggered the workflow.");
            }
        }
Пример #4
0
        /// <summary>
        /// Notify the user that there is a task waiting
        /// </summary>
        /// <param name="userAccount"></param>
        public static void NotifyUser(this DisplayFormUserTask task)
        {
            throw new NotImplementedException("This code needs to be refactored once a decision is made about the structure of email addresses has been made.");

            /*
             *          /*
             * if (task.AssignedToUser != null)
             * {
             *  string emailAddress = string.Empty;
             *  var emailContacts = task.AssignedToUser.PersonHasEmailContact;
             *  if (emailContacts != null)
             *  {
             *      var defaultEmailContact = emailContacts.FirstOrDefault(ec => ec.EmailContactIsDefault ?? false);
             *      if (defaultEmailContact != null)
             *      {
             *          emailAddress = defaultEmailContact.Name;
             *      }
             *  }
             *
             *  if (!String.IsNullOrEmpty(emailAddress))
             *  {
             *      var subject = task.Name ?? DefaultSubject;
             *
             *      var body = string.Format(MessageFormat, (task.Description), CreateActionLink(task));    //TODO: consider if this needs to be encoded
             *
             *      var emailSettings = Entity.Get<TenantEmailSetting>("tenantEmailSettingsInstance", TenantEmailSetting.AllFields);
             *
             *      if (emailSettings.TesApprovalsInbox != null && emailSettings.TesApprovalsInbox.UsesInboxProvider != null)
             *      {
             *          var mailBox = emailSettings.TesApprovalsInbox;
             *          var provider = mailBox.UsesInboxProvider;
             *          var tenantName = RequestContext.GetContext().Tenant.Name;
             *
             *          var sentMessage = new SentEmailMessage()
             *              {
             *                  EmTo = emailAddress,
             *                  EmFrom = mailBox.InboxEmailAddress,
             *                  EmSubject = subject,
             *                  EmBody = body,
             *                  EmIsHtml = true,
             *                  EmSentDate = DateTime.UtcNow,
             *                  SentFromInbox = mailBox,
             *                  RelatedTask = task.As<DisplayFormUserTask>(),
             *              };
             *
             *          sentMessage.Save();
             *
             *          var inboxProviderHelper = provider.GetHelper();
             *          inboxProviderHelper.SendMessages(sentMessage.ToMailMessage().ToEnumerable(), tenantName, mailBox.Name);
             *      }
             *  }
             * }
             */
        }
Пример #5
0
        /// <summary>
        /// Process an approval
        /// </summary>
        /// <param name="taskId">The task to approve</param>
        /// <param name="selectedOption">the name of the transition that has been selected</param>
        /// <param name="preSaveAction">An optional presave action</param>
        public static void ProcessApproval(long taskId, string selectedOption, Action <DisplayFormUserTask> preSaveAction = null)
        {
            DisplayFormUserTask task = Entity.Get <DisplayFormUserTask>(
                taskId, true, DisplayFormUserTask.UserResponse_Field,
                BaseUserTask.UserTaskCompletedOn_Field,
                DisplayFormUserTask.RelatedMessages_Field);

            var transitions = task.WorkflowRunForTask.PendingActivity.ForwardTransitions;

            var selectedTransition = transitions.First(
                t => String.Equals(t.FromExitPoint.Name, selectedOption, StringComparison.OrdinalIgnoreCase));

            ProcessApproval(task, selectedTransition, preSaveAction);
        }
Пример #6
0
        /// <summary>
        /// Process an approval
        /// </summary>
        /// <param name="taskId">The task to approve</param>
        /// <param name="selectedOption">Teh selected transition</param>
        /// <param name="preSaveAction">An optional presave action</param>
        public static void ProcessApproval(DisplayFormUserTask task, TransitionStart selectedOption, Action <DisplayFormUserTask> preSaveAction = null)
        {
            task = task.AsWritable <DisplayFormUserTask>();

            task.UserResponse        = selectedOption;
            task.UserTaskCompletedOn = DateTime.UtcNow;      // Leave this for the Before save hook, it's currently the only way to know what has changed.
            task.TaskStatus_Enum     = TaskStatusEnum_Enumeration.TaskStatusCompleted;

            if (preSaveAction != null)
            {
                preSaveAction(task);
            }

            task.Save();
        }
        void UpdateLogEntry(DisplayFormUserTask userTask)
        {
            var logEntry = userTask.LogEntryForUserAction;

            var exitPoint     = userTask.UserResponse.FromExitPoint;
            var actionSummary = !string.IsNullOrWhiteSpace(exitPoint.ExitPointActionSummary) ? exitPoint.ExitPointActionSummary: exitPoint.Name;

            var writable = logEntry.AsWritable <WorkflowUserActionLogEntry>();

            writable.WuleCompletedDate = userTask.UserTaskCompletedOn;
            writable.WuleUserComment   = userTask.TaskComment;
            writable.WuleActionSummary = actionSummary;
            writable.Description      += string.Format(", Completed: {0}, Action: {1}", userTask.UserTaskCompletedOn, actionSummary);

            writable.Save();
        }
        void CreateLogEntry(IRunState context, DisplayFormUserTask userTask)
        {
            var actingPersonName = userTask.AssignedToUser != null ? userTask.AssignedToUser.Name : null;

            // Create the log entry
            context.Log(new WorkflowUserActionLogEntry
            {
                Name                        = ActivityInstance.Name,
                LogEventTime                = DateTime.UtcNow,
                UserActionBeingLogged       = userTask,
                WuleDueDate                 = userTask.UserTaskDueOn,
                ActingPersonReferencedInLog = userTask.AssignedToUser,
                ActingPersonName            = actingPersonName,
                ObjectReferencedInLog       = userTask.RecordToPresent,
                Description                 = string.Format("Assigned to: {0}, Due: {1}", actingPersonName ?? "", userTask.UserTaskDueOn)
            });
        }
Пример #9
0
        /// <summary>
        /// Generate a page to show on completing a task.
        /// </summary>
        /// <param name="select"></param>
        /// <returns></returns>
        public string GenerateCompletedPage(DisplayFormUserTask task)
        {
            var exitPoint = task.UserResponse.FromExitPoint;

            var sb = new StringBuilder();

            GeneratePageStart(sb, task, "Completed:");

            var display = exitPoint.ExitPointActionSummary ?? exitPoint.Name;

            sb.Append("<p>");
            sb.Append(display);
            sb.Append("<p>");

            GeneratePageEnd(sb);

            return(sb.ToString());
        }
Пример #10
0
        private static void GeneratePageStart(StringBuilder sb, DisplayFormUserTask task, string intro)
        {
            sb.Append(@"
<html>
<head>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' href='assets/SoftwarePlatform.client.css' />
</head>
<body style='font-size:100%'>
");
            sb.Append(intro);
            sb.Append("<p>");

            sb.Append(HttpUtility.HtmlEncode(task.Name));

            if (task.RecordToPresent != null)
            {
                sb.Append("<p>");
                sb.Append(task.RecordToPresent.Name);
            }
        }
Пример #11
0
        /// <summary>
        /// Given a token and the options to present, generate an appropriate html page
        /// </summary>
        /// <param name="task">The task to render</param>
        /// <param name="token">The task token</param>
        /// <returns></returns>
        public string GenerateSelectionPage(DisplayFormUserTask task)
        {
            var taskToken = task.DfutLinkToken;
            var options   = task.AvailableTransitions.Select(t => t.FromExitPoint.Name);

            var sb = new StringBuilder();

            GeneratePageStart(sb, task, "User action required for:");

            sb.Append("<p><ul>");

            foreach (var option in options)
            {
                sb.Append("<li>");
                sb.Append(GenerateSelectionAnchor(taskToken, option));
                sb.Append("</li>");
            }

            GeneratePageEnd(sb);

            return(sb.ToString());
        }
        private const decimal DefaultTimeOutMins = 0;     // no time out

        public override bool OnStart(IRunState context, ActivityInputs inputs)
        {
            var assignedTo          = GetArgumentEntity <Person>(inputs, "inDisplayFormForUser");
            var recordToPresent     = GetArgumentEntity <UserResource>(inputs, "inDisplayFormResource");
            var form                = GetArgumentEntity <CustomEditForm>(inputs, "inDisplayFormForm");
            var timeoutDays         = GetArgumentValue <decimal>(inputs, "inDisplayFormTimeOut", DefaultTimeOutMins);
            var priority            = GetArgumentEntity <EventEmailPriorityEnum>(inputs, "inDisplayFormPriority");
            var activityInstanceAs  = ActivityInstance.Cast <DisplayFormActivity>();
            var percentageCompleted = GetArgumentValue <decimal?>(inputs, "inDisplayFormPercentageCompleted", null);
            var waitForNext         = GetArgumentValue <bool>(inputs, "inDisplayFormWaitForNext", false);
            var recordHistory       = GetArgumentValue <bool>(inputs, "inDisplayFormRecordHistory", false);
            var hideComment         = GetArgumentValue <bool>(inputs, "inHideComment", false);
            var openInEditMode      = GetArgumentValue <bool>(inputs, "inOpenInEditMode", false);

            priority = priority ?? Entity.Get <EventEmailPriorityEnum>(new EntityRef("core", "normalPriority"));

            var workflowRun = context.WorkflowRun;


            var dueDate = DateTime.UtcNow.AddDays((double)timeoutDays);

            var userTask = new DisplayFormUserTask
            {
                Name                 = ActivityInstance.Name ?? DefaultTitle,
                RecordToPresent      = recordToPresent,
                FormToUse            = form,
                AvailableTransitions = GetAvailableUserTransitions(),
                AssignedToUser       = assignedTo,
                TaskPriority         = priority,
                TaskStatus_Enum      = TaskStatusEnum_Enumeration.TaskStatusNotStarted,
                PercentageCompleted  = percentageCompleted,
                WaitForNextTask      = waitForNext,
                UserTaskDueOn        = dueDate,
                HideComment          = hideComment,
                OpenInEditMode       = openInEditMode,
                DfutLinkToken        = CryptoHelper.GetRandomPrintableString(8)
            };

            context.SetUserTask(userTask.Cast <BaseUserTask>());

            if (recordHistory)
            {
                CreateLogEntry(context, userTask);
            }

            SetTimeoutIfNeeded(context, timeoutDays);

            var tenantSetting = Entity.Get <TenantGeneralSettings>(WellKnownAliases.CurrentTenant.TenantGeneralSettingsInstance);

            if (Factory.FeatureSwitch.Get("enableWfUserActionNotify"))
            {
                //
                // IN PROGRESS - Please leave
                // This code is in development and switched off until email and SMS approvals are required by PM.
                //
                Notifier notifier = null; // tenantSetting.UserActionNotifier;
                if (notifier != null)
                {
                    // TODO: Format correctly for where it is being sent SMS email etc. Move the decision out of here and make the notfier decide on the type of message
                    var generator = new HtmlGenerator();

                    string message = null;
                    if (notifier.Is <EmailNotifier>())           // TODO: This is wrong, it should be somehow tied to the Router
                    {
                        var transitionOptions = userTask.AvailableTransitions.Select(t => t.FromExitPoint.Name).Where(n => !String.IsNullOrEmpty(n));

                        if (transitionOptions.Any())
                        {
                            message = generator.GenerateSelectionPage(userTask);
                        }
                    }
                    else if (notifier.Is <TwilioNotifier>())
                    {
                        message = generator.GenerateSelectionPageUrl(userTask.DfutLinkToken);
                    }

                    if (message != null)
                    {
                        var userList = userTask.AssignedToUser.ToEnumerable();

                        var notification = new Notification {
                            NMessage = message
                        };

                        //TOOD: Add alternative text in the email with a link to the SMS page
                        NotificationRouter.Instance.Send(notifier, notification, userList, false);
                    }
                }
            }

            context.SetArgValue(ActivityInstance, GetArgumentKey("core:outDisplayFormUserTask"), userTask);
            context.SetArgValue(ActivityInstance, GetArgumentKey("core:dfaInternalKeepHistory"), recordHistory);

            return(false);
        }
Пример #13
0
        //[Category( "ExtendedTests" )]
        public void TestWithWorkflowContext()
        {
            using (new WorkflowRunContext {
                RunTriggersInCurrentThread = true
            })
            {
                Workflow            myWorkflow = null;
                UserAccount         myUser     = null;
                Person              myPerson   = null;
                DisplayFormUserTask task1      = null;
                DisplayFormUserTask task2      = null;

                try
                {
                    myWorkflow = Entity.Create <Workflow>()
                                 .AddDefaultExitPoint()
                                 .AddDisplayForm("Display Form 1", new string[] { "Exit1" }, null, null, null)
                                 .AddLog("First Log", "Log 1")
                                 .AddDisplayForm("Display Form 2", new string[] { "Exit1" }, null, null, null)
                                 .AddLog("Seond Log", "Log 2");

                    myWorkflow.Name = "UNNUMBERED_DianasSecurityProblem " + DateTime.Now;
                    myWorkflow.WorkflowRunAsOwner = true;
                    myWorkflow.Save();
                    ToDelete.Add(myWorkflow.Id);

                    var myType    = CreateType("CreateTriggerAddsAndRemovesTypeHook_type", UserResource.UserResource_Type);
                    var myTrigger = CreateTrigger("CreateTriggerAddsAndRemovesTypeHook_trigger", myType, myWorkflow);

                    myType.AsWritable();
                    myType.Name = "Creatable";
                    myType.IsOfType.Add(Resource.Resource_Type);
                    myType.Save();

                    myPerson             = Entity.Create <Person>();
                    myPerson.FirstName   = "John";
                    myPerson.LastName    = "Bob";
                    myUser               = Entity.Create <UserAccount>();
                    myUser.Name          = "Bob" + DateTime.Now;
                    myUser.AccountHolder = myPerson;
                    myUser.Save();
                    ToDelete.Add(myUser.Id);

                    new AccessRuleFactory().AddAllowByQuery(myUser.As <Subject>(),
                                                            Resource.Resource_Type.As <SecurableEntity>(),
                                                            new EntityRef("core:create").ToEnumerable(),
                                                            TestQueries.EntitiesWithName("Creatable").ToReport());

                    using (new SetUser(myUser))
                        using (new WorkflowRunContext(true))
                        {
                            var e = Entity.Create(myType).As <Resource>();
                            e.Name          = "MyName";
                            e.CreatedDate   = DateTime.Now;
                            e.CreatedBy     = myUser;
                            e.SecurityOwner = myUser;
                            e.Save();
                            ToDelete.Add(e.Id);
                        }

                    Workflow    wf;
                    WorkflowRun run1;

                    wf = Entity.Get <Workflow>(myWorkflow.Id);

                    run1 = wf.RunningInstances.First();
                    Assert.That(run1, Is.Not.Null);

                    task1 = run1.TaskWithinWorkflowRun.Select(t => t.As <DisplayFormUserTask>()).FirstOrDefault(t => t != null);
                    Assert.That(task1, Is.Not.Null);

                    task1.AssignedToUser.Should().NotBeNull();
                    task1.AssignedToUser.Id.Should().Be(myPerson.Id);

                    using (new SetUser(myUser))
                        using (new WorkflowRunContext(true))
                        {
                            var writableTask = task1.AsWritable <DisplayFormUserTask>();
                            writableTask.UserResponse    = task1.AvailableTransitions.First(t => t.Name == "Exit1");
                            writableTask.TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusCompleted;
                            writableTask.Save();
                        }

                    Assert.IsTrue(WaitForWorkflowToStop(run1), "Workflow run should have completed.");

                    wf = Entity.Get <Workflow>(wf.Id);

                    var run2 = wf.RunningInstances.First();
                    Assert.That(run2, Is.Not.Null);

                    task2 = run2.TaskWithinWorkflowRun.First(t => t.Id != task1.Id).As <DisplayFormUserTask>();
                    Assert.That(task2, Is.Not.Null);

                    using (new SetUser(myUser))
                        using (new WorkflowRunContext(true))
                        {
                            var writableTask = task2.AsWritable <DisplayFormUserTask>();
                            writableTask.UserResponse    = writableTask.AvailableTransitions.First(t => t.Name == "Exit1");
                            writableTask.TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusCompleted;
                            writableTask.Save();
                        }

                    Assert.IsTrue(WaitForWorkflowToStop(run2), "Workflow run should have completed.");
                }
                finally
                {
                    if (task1 != null)
                    {
                        ToDelete.Add(task1.Id);
                    }
                    if (task2 != null)
                    {
                        ToDelete.Add(task2.Id);
                    }
                    if (myWorkflow != null)
                    {
                        ToDelete.Add(myWorkflow.Id);
                    }
                    if (myUser != null)
                    {
                        ToDelete.Add(myUser.Id);
                    }
                    if (myPerson != null)
                    {
                        ToDelete.Add(myPerson.Id);
                    }
                }
            }
        }
Пример #14
0
        public void TestDisplayFormResumeWithPromptActivity_Bug_27060()
        {
            using (new WorkflowRunContext {
                RunTriggersInCurrentThread = true
            })
            {
                Workflow            wf   = null;
                DisplayFormUserTask task = null;
                PromptUserTask      p    = null;

                try
                {
                    WorkflowRun run, run2, run3;


                    // Arrange
                    var cheese  = new EntityRef("test", "cheese");
                    var cheeses = Entity.GetInstancesOfType(cheese);

                    //
                    // IMPORTANT: the point is to NOT set a value on the variable for this test!
                    //            the run state serialization that occurs when pausing must realize that the variable is used
                    //            subsequently.
                    //
                    wf = Entity.Create <Workflow>()
                         .AddDefaultExitPoint()
                         .AddVariable <ResourceArgument>("myVar", null, Entity.Get <EntityType>(new EntityRef("test", "employee")))
                         //.AddEntityExpressionToVariable("myVar", new EntityRef("test", "aaJudeJacobs"))
                         .AddInput <ResourceArgument>("myInput", Entity.Get <EntityType>(cheese))
                         .AddDisplayForm("Display Form", new[] { "Exit1", "Exit2" }, recordExpression: "[myInput]")
                         .AddPromptUser("Prompt User")
                         .AddLog("Log", "MyVar: {{myVar}}");

                    wf.Name = "!TestDisplayFormResumeWithVariables_Bug_23903_" + DateTime.Now;

                    wf.Save();

                    // Act
                    var wfInput = new Dictionary <string, object> {
                        { "myInput", cheeses.First() }
                    };

                    using (new WorkflowRunContext(true))
                    {
                        run = RunWorkflow(wf, wfInput);
                    }

                    run.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunPaused);
                    run.PendingActivity.Should().NotBeNull();
                    run.PendingActivity.Name.Should().Be("Display Form");
                    run.TaskWithinWorkflowRun.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1);

                    task = run.TaskWithinWorkflowRun.First().AsWritable <DisplayFormUserTask>();
                    task.Should().NotBeNull();

                    run.StateInfo.Count.Should().BeGreaterOrEqualTo(2);
                    run.StateInfo.Select(si => si.StateInfoArgument.Name).Should().NotContain("myVar");
                    run.StateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myInput");

                    using (new WorkflowRunContext(true))
                    {
                        run2 = WorkflowRunner.Instance.ResumeWorkflow(run, new UserCompletesTaskEvent
                        {
                            CompletionStateId = task.AvailableTransitions.First(t => t.Name == "Exit1").Id,
                            UserTaskId        = task.Id
                        });
                    }

                    run2.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunPaused);
                    run2.PendingActivity.Should().NotBeNull();
                    run2.PendingActivity.Name.Should().Be("Prompt User");
                    run2.TaskWithinWorkflowRun.Should().NotBeNull().And.NotBeEmpty().And.HaveCount(1);

                    p = run2.TaskWithinWorkflowRun.First().AsWritable <PromptUserTask>();
                    p.Should().NotBeNull();

                    p.PromptForTaskStateInfo.Should().NotBeNull().And.HaveCount(2);
                    p.PromptForTaskStateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myVar");
                    p.PromptForTaskStateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myInput");

                    run2.StateInfo.Count.Should().BeGreaterOrEqualTo(3);
                    run2.StateInfo.Select(si => si.StateInfoArgument.Name).Should().NotContain("myVar");
                    run2.StateInfo.Select(si => si.StateInfoArgument.Name).Should().Contain("myInput");

                    var value = p.PromptForTaskStateInfo.First(si => si.StateInfoArgument.Name == "myVar");
                    var param = value.StateInfoValue.AsWritable <ResourceArgument>();
                    param.ResourceParameterValue = Entity.Get <Resource>(new EntityRef("test", "aaJudeJacobs"));
                    param.Save();

                    var param2 = Entity.Get <ResourceArgument>(param);
                    param2.ResourceParameterValue.Should().NotBeNull();
                    param2.ResourceParameterValue.Name.Should().Be("Jude Jacobs");

                    using (new WorkflowRunContext(true))
                    {
                        run3 = WorkflowRunner.Instance.ResumeWorkflow(run2, new PromptUserTaskCompletedEvent
                        {
                            UserTaskId = p.Id
                        });
                    }

                    // Assert
                    run3.WorkflowRunStatus_Enum.Should().Be(WorkflowRunState_Enumeration.WorkflowRunCompleted);
                    run3.RunLog.Should().NotBeNull().And.NotBeEmpty();
                    run3.RunLog.Where(l => l.Description == "MyVar: Jude Jacobs").Should().NotBeEmpty();
                }
                finally
                {
                    if (p != null)
                    {
                        ToDelete.Add(p.Id);
                    }
                    if (task != null)
                    {
                        ToDelete.Add(task.Id);
                    }
                    if (wf != null)
                    {
                        ToDelete.Add(wf.Id);
                    }
                }
            }
        }