title: How do I create a new customer in a test codeunit through UI?
body: <p>I would like to simulate the creation of something like a customer, item or invoice, although through the use of <em>test pages</em>. My first thought was to use the <code>OpenNew()</code>-function:</p>
  <pre><code>[Test]
  [HandlerFunctions('ModalPageHandler,ExpectedConfirmHandler')]
  procedure SampleTest()
  // [FEATURE] Customer
  // [SCENARIO] Create a new Customer
  // [PREREQ] super rights not necessary
  var
    tpCustomerCard: TestPage &quot;Customer Card&quot;;
    cNewCustomerNo: Code[20];
    rCustomer: Record Customer;
  begin
    Initialize();
  
    // [GIVEN] Office 365 Business Full permissions
    gAny.SetSeed(5);
    gLibraryLowerPermissions.SetO365BusFull();
  
    // [WHEN] Creating a new user
    tpCustomerCard.OpenNew();
    tpCustomerCard.Name.SetValue(gAny.AlphabeticText(gAny.IntegerInRange(20)));
    cNewCustomerNo := tpCustomerCard.&quot;No.&quot;.Value;
    gLibraryVariableStorage.Enqueue('');
    gLibraryVariableStorage.Enqueue(true);
    tpCustomerCard.Close();
  
    // [THEN] create user
    gAssert.IsFalse(cNewCustomerNo = '', 'New Customer No. created');
    gAssert.IsTrue(rCustomer.Get(cNewCustomerNo), 'New Customer created');
  end;
  
  [ModalPageHandler]
  procedure ModalPageHandler(var tpCustomerCard: TestPage &quot;Customer Card&quot;);
  begin
  end;
  
  [ConfirmHandler]
  procedure ExpectedConfirmHandler(pQuestion: Text[1024]; VAR pvReply: Boolean)
  // Call the following in the Test function
  //gLibraryVariableStorage.Enqueue('ExpectedConfirmText');
  //gLibraryVariableStorage.Enqueue(true); // or false, depending of the reply you want if below question is asked. Any other question will throw an error
  begin
    gAssert.ExpectedMessage(gLibraryVariableStorage.DequeueText(), pQuestion);
    pvReply := gLibraryVariableStorage.DequeueBoolean();
  end;
  </code></pre>
  <p>However, this would always return the following error:</p>
  <pre><code>Unexpected CLR exception thrown.: Microsoft.Dynamics.Framework.UI.FormAbortException: Page New - Customer Card has to close. ---&gt; Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLMissingUIHandlerException: Unhandled UI: ModalPage 1340 ---&gt; System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---&gt; Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLMissingUIHandlerException: Unhandled UI: ModalPage 1340\   at Microsoft.Dynamics.Nav.Runtime.NavTestExecution.FindHandler(NavHandlerType handlerType, NavApplicationObjectBase appObject, Boolean throwIfNotFound, String handlerDescription)\   at Microsoft.Dynamics.Nav.Runtime.NavTestExecution.TestHandleModalForm(NavForm form, FormResult&amp; action, NavFormRuntimeParameters parameters)\   at Microsoft.Dynamics.Nav.Runtime.NavForm.RunModal(NavRecord record, Int32 fieldNo)\   at Microsoft.Dynamics.Nav.Runtime.NavFormHandle.RunModal(NavRecord record, Int32 fieldNo)\   at Microsoft.Dynamics.Nav.BusinessApplication.Record1300.NewCustomerFromTemplate_Scope__1848449490.OnRun()\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Record1300.NewCustomerFromTemplate(INavRecordHandle customer)\   at Microsoft.Dynamics.Nav.BusinessApplication.Record1300.OnInvoke(Int32 memberId, Object[] args)\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1389.CreateCustomerFromConfigTemplate_Scope_587295807.OnRun()\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1389.CreateCustomerFromConfigTemplate(INavRecordHandle customer, ByRef`1 isHandled)\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1389.OnInsertCustomerFromTemplateHandler_Scope.OnRun()\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1389.OnInsertCustomerFromTemplateHandler(INavRecordHandle customer, ByRef`1 result, ByRef`1 isHandled)\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1389.OnInvoke(Int32 memberId, Object[] args)\   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriberInternal(NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)\   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.CallEventSubscriber(NavApplicationObjectBase callingApplicationObject, NavEventSubscription subscriber, NavApplicationObjectBase subscriberInstance, Object[] parameters)\   at Microsoft.Dynamics.Nav.EventSubscription.NavEventScope.ProcessCallToTypeAndManualSubscriptions(NavApplicationObjectBase callerApplicationObject, NavEventSubscription[] subscriptions, PrepareParametersCallBack prepareParameters)\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.RunEvent()\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1381.OnInsertCustomerFromTemplate(INavRecordHandle customer, ByRef`1 result, ByRef`1 isHandled)\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1381.InsertCustomerFromTemplate(INavRecordHandle customer)\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit1381.OnInvoke(Int32 memberId, Object[] args)\   at Microsoft.Dynamics.Nav.BusinessApplication.Page21.CreateCustomerFromTemplate_Scope_857168676.OnRun()\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Page21.CreateCustomerFromTemplate()\   at Microsoft.Dynamics.Nav.BusinessApplication.Page21.OnAfterGetCurrRecord_Scope.OnRun()\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Page21.OnAfterGetCurrRecord()\   at Microsoft.Dynamics.Nav.Runtime.NavForm.RaiseOnAfterGetCurrRecord()\   at Microsoft.Dynamics.Nav.Runtime.NavForm.AfterGetCurrRecord()\   --- End of inner exception stack trace ---\   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)\   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)\   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\   at Microsoft.Dynamics.Nav.Runtime.NavApplicationMethod.InvokeMethod(ITreeObject obj, String methodName, Object[] args, Boolean resolveHandler, Boolean throwOnNotFound)\   --- End of inner exception stack trace ---\   at Microsoft.Dynamics.Nav.Runtime.NavApplicationMethod.InvokeMethod(ITreeObject obj, String methodName, Object[] args, Boolean resolveHandler, Boolean throwOnNotFound)\   at Microsoft.Dynamics.Nav.Service.NSFormApplicationCode.&lt;&gt;c__DisplayClass7_0.&lt;Invoke&gt;b__0(NsDataAccess dataAccess)\   at Microsoft.Dynamics.Nav.Service.NsFormDataAccess.RunWithFormDataAccess[T](ITreeObject parent, NavForm form, Func`2 func)\   at Microsoft.Dynamics.Nav.Service.NsDataAccess.RunWithDataAccess[T](ITreeObject parent, NavRecordState state, Boolean instantiateNewForm, Guid parentFormHandle, String parentControlName, Boolean&amp; instantiatedForm, Func`2 func)\   at Microsoft.Dynamics.Nav.Service.NsDataAccess.RunWithDataAccess[T](ITreeObject parent, NavRecordState state, Func`2 func)\   at INavServiceWrapper.InvokeApplicationMethod(ApplicationMethodRequest , NavRecordState )\   at Microsoft.Dynamics.Nav.Types.AsyncNavServiceWrapper.&lt;&gt;c__DisplayClass119_0.&lt;BeginInvokeApplicationMethod&gt;b__0()\   at Microsoft.Dynamics.Nav.Types.AsyncNavServiceWrapper.Invoke(Func`1 action, AsyncCallback callback, Object asyncState, Object extraState)\   at Microsoft.Dynamics.Nav.Client.ServiceConnectionBase.&lt;&gt;c__DisplayClass21_0.&lt;InvokeApplicationMethod&gt;b__0(IAsyncNavService server)\   at Microsoft.Dynamics.Nav.Runtime.TestServiceConnection.CallServer[T](BeginCallServerMethod beginCallServerMethod, EndCallServerMethod`1 endCallServerMethod)\   at Microsoft.Dynamics.Nav.Client.ServiceConnectionBase.InvokeApplicationMethod(ApplicationCodeType objectType, Int32 objectId, String methodName, NavDataSet&amp; dataSet, NavRecordState&amp; state, Object[]&amp; args)\   at Microsoft.Dynamics.Nav.Client.DataBinder.NstDataAccess.InvokeOnAfterGetCurrentRecord(NavDataSet&amp; navDataSet, NavRecordState&amp; navRecordState)\   at Microsoft.Dynamics.Nav.Client.DataBinder.NstDataAccess.InvokeOnNewRecord(NavRecord record, NavRecord xrec, NavRecordState state, Object[] args)\   at Microsoft.Dynamics.Nav.Client.DataBinder.NstDataAccess.OnNewRecord(Boolean clearFormState, NavRecord xrec, Object[] args)\   --- End of inner exception stack trace ---\   at Microsoft.Dynamics.Nav.Client.DataBinder.NstDataAccess.Abort(NavBaseException exception)\   at Microsoft.Dynamics.Nav.Client.DataBinder.NstDataAccess.OnNewRecord(Boolean clearFormState, NavRecord xrec, Object[] args)\   at Microsoft.Dynamics.Nav.Client.DataBinder.NavBindingManager.EnsureOnNewRecordIsUpToDate()\   at Microsoft.Dynamics.Nav.Client.DataBinder.NavBindingManager.OnCurrentRowChanged(CurrentRowChangeEventArgs e)\   at Microsoft.Dynamics.Framework.UI.BindingManager.set_CurrentCollectionIndex(Int32 value)\   at Microsoft.Dynamics.Framework.UI.VirtualRows.UpdateAfterInsert(Int32 index, Boolean needsUpdateCurrentRow)\   at Microsoft.Dynamics.Framework.UI.VirtualRows.AddWithoutValidation(RowEntry row, Boolean needsUpdateCall, Boolean needsUpdateCurrentRow, Boolean insertFirst, Boolean raiseEvents)\   at Microsoft.Dynamics.Framework.UI.VirtualRows.Insert()\   at Microsoft.Dynamics.Nav.Client.TestPageClient.TestPageClientSession.CreateLogicalForm(Int32 formId, FormState formState)\   at Microsoft.Dynamics.Nav.Client.TestPageClient.TestPageClientSession.CreatePage(Int32 id, ViewMode mode)\   at Microsoft.Dynamics.Nav.Runtime.NavTestPage.Open(ViewMode mode)\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit50100.SampleTest_Scope__1526614456.OnRun()\   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()\   at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit50100.SampleTest()
  </code></pre>
  <p>When <em>debugging</em>, the code <em>automatically breaks</em> at this function in <code>Mini Customer Template.dal</code>, even without breakpoints:</p>
  <pre><code>[Obsolete('Will be removed with other functionality related to &quot;old&quot; templates. Replaced by new templates.', '18.0')]
      procedure NewCustomerFromTemplate(var Customer: Record Customer): Boolean
      var
          ConfigTemplateHeader: Record &quot;Config. Template Header&quot;;
          ConfigTemplates: Page &quot;Config Templates&quot;;
      begin
          ConfigTemplateHeader.SetRange(&quot;Table ID&quot;, DATABASE::Customer);
          ConfigTemplateHeader.SetRange(Enabled, true);
  
          if ConfigTemplateHeader.Count = 1 then begin
              ConfigTemplateHeader.FindFirst;
              InsertCustomerFromTemplate(ConfigTemplateHeader, Customer);
              exit(true);
          end;
  
          if (ConfigTemplateHeader.Count &gt; 1) and GuiAllowed then begin
              ConfigTemplates.SetTableView(ConfigTemplateHeader);
              ConfigTemplates.LookupMode(true);
              ConfigTemplates.SetNewMode;
              if ConfigTemplates.RunModal = ACTION::LookupOK then begin
                  ConfigTemplates.GetRecord(ConfigTemplateHeader);
                  InsertCustomerFromTemplate(ConfigTemplateHeader, Customer);
                  exit(true);
              end;
          end;
  
          exit(false);
      end;
  </code></pre>
  <p>To be specific, it always stops at the last <code>if</code>, most likely because <code>ConfigTemplates</code> is <em>undefined</em>. This probably is because when normally creating a new customer or item, the page <code>Config Templates</code> is opened first to let the user pick a template, and since my codeunit is skipping this step, one of the variables ends up being undefined. I then tried to open the <code>Customer Card</code> page by invoking the <code>New Customer</code> action from the <code>Customer List</code> page, but since that is not a custom action, I can't reach it.</p>
  <p>To replicate user interaction as closely as possible I'd prefer to open windows through actions found in the UI, but if that's impossible with AL, I'd at least want the former method to work. How can I open a card page using templates without the test immediately failing?</p>