From d35dce9ab3c554101ec386e07d1f519c033570c2 Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Tue, 8 Apr 2025 17:50:45 -0600 Subject: [PATCH 1/7] Added the 'FinishAsync' public method. --- .../Components/Wizard/FluentWizard.razor.cs | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/Core/Components/Wizard/FluentWizard.razor.cs b/src/Core/Components/Wizard/FluentWizard.razor.cs index 054e2df9cd..4397bc0d48 100644 --- a/src/Core/Components/Wizard/FluentWizard.razor.cs +++ b/src/Core/Components/Wizard/FluentWizard.razor.cs @@ -234,13 +234,37 @@ protected virtual async Task OnStepChangeHandle /// protected virtual async Task OnFinishHandlerAsync(MouseEventArgs e) { - // Validate any form edit contexts - var allEditContextsAreValid = _steps[Value].ValidateEditContexts(); - if (!allEditContextsAreValid) + await this.FinishAsync(true); + } + + /// + /// Navigate to the specified step, with or without validate the current EditContexts. + /// + /// Index number of the step to display + /// Validate the EditContext. Default is false. + /// + public Task GoToStepAsync(int step, bool validateEditContexts = false) + { + return ValidateAndGoToStepAsync(step, validateEditContexts); + } + + /// + /// Optionally validate and invoke the handler. + /// + /// Validate the EditContext. Default is false. + /// + public async Task FinishAsync(bool validateEditContexts = false) + { + if (validateEditContexts) { - // Invoke the 'OnInvalidSubmit' handlers for the edit forms. - await _steps[Value].InvokeOnInValidSubmitForEditFormsAsync(); - return; + // Validate any form edit contexts + var allEditContextsAreValid = _steps[Value].ValidateEditContexts(); + if (!allEditContextsAreValid) + { + // Invoke the 'OnInvalidSubmit' handlers for the edit forms. + await _steps[Value].InvokeOnInValidSubmitForEditFormsAsync(); + return; + } } // Invoke the 'OnValidSubmit' handlers for the edit forms. @@ -255,17 +279,6 @@ protected virtual async Task OnFinishHandlerAsync(MouseEventArgs e) } } - /// - /// Navigate to the specified step, with or without validate the current EditContexts. - /// - /// Index number of the step to display - /// Validate the EditContext. Default is false. - /// - public Task GoToStepAsync(int step, bool validateEditContexts = false) - { - return ValidateAndGoToStepAsync(step, validateEditContexts); - } - internal async Task ValidateAndGoToStepAsync(int targetIndex, bool validateEditContexts) { var stepChangeArgs = await OnStepChangeHandlerAsync(targetIndex, validateEditContexts); From 4ac88435fc525bd86dbff8ffd01924b65320a59c Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Tue, 8 Apr 2025 18:06:00 -0600 Subject: [PATCH 2/7] Updated the demo site. --- ...crosoft.FluentUI.AspNetCore.Components.xml | 9 ++++++- .../Wizard/Examples/WizardCustomized.razor | 25 +++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index f1020e140f..540ba4f6e5 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -4949,7 +4949,7 @@ - Custom icon loaded from + Custom icon loaded from @@ -10573,6 +10573,13 @@ Validate the EditContext. Default is false. + + + Optionally validate and invoke the handler. + + Validate the EditContext. Default is false. + + diff --git a/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor b/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor index 0e5b1790a9..8aeb1015ee 100644 --- a/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor +++ b/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor @@ -2,20 +2,21 @@ +Id="customized-wizard" +@bind-Value="@Value" +StepTitleHiddenWhen="@GridItemHidden.XsAndDown" +OnFinish="OnFinish" +Height="300px"> @@ -86,6 +87,10 @@ Next Go to last page } + else + { + Finish + } } @@ -100,4 +105,10 @@ { DemoLogger.WriteLine($"Go to step {e.TargetLabel} (#{e.TargetIndex})"); } + + async Task OnFinish() + { + DemoLogger.WriteLine($"Customized wizard finish clicked."); + await DialogService.ShowInfoAsync("The wizard has finished.", "Finished Clicked"); + } } From e6ba29298c8339d0663fc1d3e42464a8fb1c8709 Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Tue, 8 Apr 2025 18:16:17 -0600 Subject: [PATCH 3/7] Fixed whitespace changes. --- .../Shared/Pages/Wizard/Examples/WizardCustomized.razor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor b/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor index 8aeb1015ee..52311c04a0 100644 --- a/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor +++ b/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor @@ -2,12 +2,12 @@ From c0b9358c33336bf1d3b4e56cbb5206cfd7abe2be Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Tue, 8 Apr 2025 18:16:56 -0600 Subject: [PATCH 4/7] Additional whitespace fixes. --- .../Pages/Wizard/Examples/WizardCustomized.razor | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor b/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor index 52311c04a0..6fc4606063 100644 --- a/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor +++ b/examples/Demo/Shared/Pages/Wizard/Examples/WizardCustomized.razor @@ -12,11 +12,11 @@ + Id="customized-wizard" + @bind-Value="@Value" + StepTitleHiddenWhen="@GridItemHidden.XsAndDown" + OnFinish="OnFinish" + Height="300px"> From 31db0497bac4408a680171ea12297d8536955059 Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Tue, 8 Apr 2025 18:18:31 -0600 Subject: [PATCH 5/7] Move method for better PR experience. --- .../Components/Wizard/FluentWizard.razor.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Core/Components/Wizard/FluentWizard.razor.cs b/src/Core/Components/Wizard/FluentWizard.razor.cs index 4397bc0d48..79c58c8126 100644 --- a/src/Core/Components/Wizard/FluentWizard.razor.cs +++ b/src/Core/Components/Wizard/FluentWizard.razor.cs @@ -237,17 +237,6 @@ protected virtual async Task OnFinishHandlerAsync(MouseEventArgs e) await this.FinishAsync(true); } - /// - /// Navigate to the specified step, with or without validate the current EditContexts. - /// - /// Index number of the step to display - /// Validate the EditContext. Default is false. - /// - public Task GoToStepAsync(int step, bool validateEditContexts = false) - { - return ValidateAndGoToStepAsync(step, validateEditContexts); - } - /// /// Optionally validate and invoke the handler. /// @@ -279,6 +268,17 @@ public async Task FinishAsync(bool validateEditContexts = false) } } + /// + /// Navigate to the specified step, with or without validate the current EditContexts. + /// + /// Index number of the step to display + /// Validate the EditContext. Default is false. + /// + public Task GoToStepAsync(int step, bool validateEditContexts = false) + { + return ValidateAndGoToStepAsync(step, validateEditContexts); + } + internal async Task ValidateAndGoToStepAsync(int targetIndex, bool validateEditContexts) { var stepChangeArgs = await OnStepChangeHandlerAsync(targetIndex, validateEditContexts); From ccf7f120e16373c8d85da7d91b85149dd61a22b1 Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Wed, 9 Apr 2025 07:58:49 -0600 Subject: [PATCH 6/7] Added the requested unit tests. --- ...crosoft.FluentUI.AspNetCore.Components.xml | 10 +- ...textIsInValid_OnFinish.verified.razor.html | 47 ++ ...ontextIsInValid_OnNext.verified.razor.html | 47 ++ ...orm_EditContextIsValid.verified.razor.html | 42 ++ tests/Core/Wizard/FluentWizardTests.razor | 592 ++++++++++++------ 5 files changed, 531 insertions(+), 207 deletions(-) create mode 100644 tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnFinish.verified.razor.html create mode 100644 tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnNext.verified.razor.html create mode 100644 tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsValid.verified.razor.html diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 540ba4f6e5..357318762a 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -10565,18 +10565,18 @@ - + - Navigate to the specified step, with or without validate the current EditContexts. + Optionally validate and invoke the handler. - Index number of the step to display Validate the EditContext. Default is false. - + - Optionally validate and invoke the handler. + Navigate to the specified step, with or without validate the current EditContexts. + Index number of the step to display Validate the EditContext. Default is false. diff --git a/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnFinish.verified.razor.html b/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnFinish.verified.razor.html new file mode 100644 index 0000000000..b7813f3e2e --- /dev/null +++ b/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnFinish.verified.razor.html @@ -0,0 +1,47 @@ + +
+
    +
  1. +
    + +
    +
    +

    +

    +
    +
  2. +
  3. +
    + +
    +
    +

    +

    +
    +
  4. +
+
+
+
+ +
+
+
+
+
+
    +
  • The field NumberBetween1and10 must be between 1 and 10.
  • +
+
+ +
+
+
+
+ Finish +
+
\ No newline at end of file diff --git a/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnNext.verified.razor.html b/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnNext.verified.razor.html new file mode 100644 index 0000000000..5d16aeab07 --- /dev/null +++ b/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnNext.verified.razor.html @@ -0,0 +1,47 @@ + +
+
    +
  1. +
    + +
    +
    +

    +

    +
    +
  2. +
  3. +
    + +
    +
    +

    +

    +
    +
  4. +
+
+
+
+
+
    +
  • The field NumberBetween1and10 must be between 1 and 10.
  • +
+
+ +
+
+
+
+ +
+
+
+
+ Next +
+
\ No newline at end of file diff --git a/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsValid.verified.razor.html b/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsValid.verified.razor.html new file mode 100644 index 0000000000..961b61b319 --- /dev/null +++ b/tests/Core/Wizard/FluentWizardTests.FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsValid.verified.razor.html @@ -0,0 +1,42 @@ + +
+
    +
  1. +
    + +
    +
    +

    +

    +
    +
  2. +
  3. +
    + +
    +
    +

    +

    +
    +
  4. +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ Finish +
+
\ No newline at end of file diff --git a/tests/Core/Wizard/FluentWizardTests.razor b/tests/Core/Wizard/FluentWizardTests.razor index 077d58cedd..2560e29152 100644 --- a/tests/Core/Wizard/FluentWizardTests.razor +++ b/tests/Core/Wizard/FluentWizardTests.razor @@ -18,18 +18,18 @@ { // Arrange && Act var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - ); + + + Content 1 + + + Content 2 + + + Content 3 + + + ); // Assert cut.Markup.Contains("position=\"left\""); @@ -41,18 +41,18 @@ { // Arrange && Act var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - ); + + + Content 1 + + + Content 2 + + + Content 3 + + + ); // Assert cut.Markup.Contains("position=\"top\""); @@ -64,18 +64,18 @@ { // Arrange && Act var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); // Assert @@ -90,18 +90,18 @@ // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); @@ -124,18 +124,18 @@ { // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); @@ -156,18 +156,18 @@ // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); @@ -183,18 +183,18 @@ { // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - ); + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); nextButton.Click(); @@ -211,18 +211,18 @@ { // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - ); + + + Content 1 + + + Content 2 + + + Content 3 + + + ); for (int i = 0; i < nextCount; i++) { @@ -239,25 +239,25 @@ { // Arrange var cut = Render(@ - - - - @GetStepContent(context) - - - Content 1 - - - - - @GetStepContent(context) - - - Content 2 - - - - + + + + @GetStepContent(context) + + + Content 1 + + + + + @GetStepContent(context) + + + Content 2 + + + + ); // Assert @@ -273,33 +273,33 @@ public void FluentWizard_EditForm_EditContextIsValid() { var testRecord1 = new TestRecord - { - NumberBetween1and10 = 5, - }; + { + NumberBetween1and10 = 5, + }; var testRecord2 = new TestRecord - { - NumberBetween1and10 = 7, - }; + { + NumberBetween1and10 = 7, + }; var cut = Render(@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); bool finishHandled = false; @@ -327,33 +327,33 @@ int stepIndex = 0; var testRecord1 = new TestRecord - { - NumberBetween1and10 = 15, - }; + { + NumberBetween1and10 = 15, + }; var testRecord2 = new TestRecord - { - NumberBetween1and10 = 15, - }; + { + NumberBetween1and10 = 15, + }; var cut = Render(@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); bool finishHandled = false; @@ -380,33 +380,33 @@ public void FluentWizard_EditForm_EditContextIsInValid_OnFinish() { var testRecord1 = new TestRecord - { - NumberBetween1and10 = 5, - }; + { + NumberBetween1and10 = 5, + }; var testRecord2 = new TestRecord - { - NumberBetween1and10 = 15, - }; + { + NumberBetween1and10 = 15, + }; var cut = Render(@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); bool finishHandled = false; @@ -439,18 +439,18 @@ // Arrange && Act var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); // Assert before any click on Next button @@ -487,12 +487,12 @@ { // Arrange var cut = Render(@ - - - - - - + + + + + + ); // Act: Click @@ -506,6 +506,194 @@ Assert.Contains("Done", cut.Markup); } + [Fact] + public void FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnNext() + { + int stepIndex = 0; + + var testRecord1 = new TestRecord + { + NumberBetween1and10 = 15, + }; + + var testRecord2 = new TestRecord + { + NumberBetween1and10 = 15, + }; + + FluentWizard fluentWizard = default!; + + var cut = Render(@ + + + + + + + + + + + + + + + + + + Next + + + ); + + bool finishHandled = false; + + for (var i = 0; i < 2; i++) + { + var nextButton = cut.Find("fluent-button[appearance='accent']"); + nextButton.Click(); + } + + // Assert + cut.Verify(); + + void OnFinishHandler() + { + finishHandled = true; + } + + Assert.False(finishHandled); + Assert.Equal(0, stepIndex); + } + + [Fact] + public void FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsInValid_OnFinish() + { + var testRecord1 = new TestRecord + { + NumberBetween1and10 = 5, + }; + + var testRecord2 = new TestRecord + { + NumberBetween1and10 = 15, + }; + + FluentWizard fluentWizard = default!; + + var cut = Render(@ + + + + + + + + + + + + + + + + + + @if (fluentWizard!.Value == 0) + { + Next + } + else + { + Finish + } + + + ); + + bool finishHandled = false; + + for (var i = 0; i < 2; i++) + { + var nextButton = cut.Find("fluent-button[appearance='accent']"); + nextButton.Click(); + } + + // Assert + cut.Verify(); + + void OnFinishHandler() + { + finishHandled = true; + } + + Assert.False(finishHandled); + } + + [Fact] + public void FluentWizard_CustomizedButtonTemplate_EditForm_EditContextIsValid() + { + var testRecord1 = new TestRecord + { + NumberBetween1and10 = 5, + }; + + var testRecord2 = new TestRecord + { + NumberBetween1and10 = 7, + }; + + FluentWizard fluentWizard = default!; + + var cut = Render(@ + + + + + + + + + + + + + + + + + + @if (fluentWizard!.Value == 0) + { + Next + } + else + { + Finish + } + + + ); + + bool finishHandled = false; + + for (var i = 0; i < 2; i++) + { + var nextButton = cut.Find("fluent-button[appearance='accent']"); + nextButton.Click(); + } + + // Assert + cut.Verify(); + + void OnFinishHandler() + { + finishHandled = true; + } + + Assert.True(finishHandled); + } + private record TestRecord { [Range(1, 10)] From 65187743fd7d01a175baad7c4b3fdaed9b7b0506 Mon Sep 17 00:00:00 2001 From: Steven Rasmussen Date: Wed, 9 Apr 2025 08:04:18 -0600 Subject: [PATCH 7/7] Fixed whitespace inconsistencies. --- tests/Core/Wizard/FluentWizardTests.razor | 276 +++++++++++----------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/tests/Core/Wizard/FluentWizardTests.razor b/tests/Core/Wizard/FluentWizardTests.razor index 2560e29152..21c0174f29 100644 --- a/tests/Core/Wizard/FluentWizardTests.razor +++ b/tests/Core/Wizard/FluentWizardTests.razor @@ -64,18 +64,18 @@ { // Arrange && Act var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); // Assert @@ -90,18 +90,18 @@ // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); @@ -124,18 +124,18 @@ { // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); @@ -156,18 +156,18 @@ // Arrange var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); var nextButton = cut.Find("fluent-button[appearance='accent']"); @@ -239,25 +239,25 @@ { // Arrange var cut = Render(@ - - - - @GetStepContent(context) - - - Content 1 - - - - - @GetStepContent(context) - - - Content 2 - - - - + + + + @GetStepContent(context) + + + Content 1 + + + + + @GetStepContent(context) + + + Content 2 + + + + ); // Assert @@ -283,23 +283,23 @@ }; var cut = Render(@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); bool finishHandled = false; @@ -337,23 +337,23 @@ }; var cut = Render(@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); bool finishHandled = false; @@ -390,23 +390,23 @@ }; var cut = Render(@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ); bool finishHandled = false; @@ -439,18 +439,18 @@ // Arrange && Act var cut = Render(@ - - - Content 1 - - - Content 2 - - - Content 3 - - - + + + Content 1 + + + Content 2 + + + Content 3 + + + ); // Assert before any click on Next button @@ -487,12 +487,12 @@ { // Arrange var cut = Render(@ - - - - - - + + + + + + ); // Act: Click @@ -607,8 +607,8 @@ { Finish } - - + + ); bool finishHandled = false;