Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e9388bf
Rewrite current UI test and add new UI test to test failing scenario
nicolaihenriksen Nov 4, 2022
4d9c233
Refactor PasswordBoxAssist to use behavior
nicolaihenriksen Nov 4, 2022
90471ba
Refactor PasswordBox reveal style TextBox focus- and text selection code
nicolaihenriksen Nov 4, 2022
0a9f4f8
Undo wrong change in TestBase
nicolaihenriksen Nov 4, 2022
bc349fa
Whitespace commit to force re-run
nicolaihenriksen Nov 4, 2022
bd746b4
Increase delay in test
nicolaihenriksen Nov 4, 2022
b282e6c
Rollback of increased test delay
nicolaihenriksen Nov 4, 2022
dda88f8
Update MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBeh…
nicolaihenriksen Nov 5, 2022
7d32386
Update MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBeh…
nicolaihenriksen Nov 5, 2022
e1ddcf8
Extract PasswordBoxBehavior into its own class
nicolaihenriksen Nov 5, 2022
847d6ab
Cache PropertyInfos and MethodInfos in PasswordBoxRevealTextBoxBehavior
nicolaihenriksen Nov 5, 2022
417c69c
Selecting minimum required version of dependency and updating nuspec
nicolaihenriksen Nov 5, 2022
4b78de6
Convert Password binding to opt-in feature
nicolaihenriksen Nov 6, 2022
3fdb918
File scoped namespace
nicolaihenriksen Nov 6, 2022
e89ce21
Behavior classes renames and change from internal to public
nicolaihenriksen Nov 6, 2022
21d7373
Use latest version of Xaml.Behaviors and update nuspec file
nicolaihenriksen Nov 6, 2022
da46c37
Attempting fix of pipeline
Keboo Nov 7, 2022
8124883
Adding screenshots for debugging
Keboo Nov 7, 2022
fac1639
Attempt at fixing failing UI test
nicolaihenriksen Nov 7, 2022
b52a9ce
Adding more screenshots for debugging
nicolaihenriksen Nov 7, 2022
100bad6
Activate test window on loaded event
nicolaihenriksen Nov 7, 2022
bfbd3d5
Yet another attempt at getting test window shown
nicolaihenriksen Nov 7, 2022
afbc730
Removing debugging screenshots
nicolaihenriksen Nov 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Rewrite current UI test and add new UI test to test failing scenario
  • Loading branch information
nicolaihenriksen committed Nov 7, 2022
commit e9388bf21d97c922b9ef84b692826beb676a3a39
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<UserControl x:Class="MaterialDesignThemes.UITests.Samples.PasswordBox.BoundPasswordBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MaterialDesignThemes.UITests.Samples.PasswordBox"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:BoundPasswordBoxViewModel, IsDesignTimeCreatable=False}"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<PasswordBox x:Name="PasswordBox"
Width="400"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource {x:Type PasswordBox}}"
materialDesign:PasswordBoxAssist.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace MaterialDesignThemes.UITests.Samples.PasswordBox;

public partial class BoundPasswordBox
{


public string? ViewModelPassword
{
get => ((BoundPasswordBoxViewModel) DataContext).Password;
set => ((BoundPasswordBoxViewModel) DataContext).Password = value;
}


private bool _useRevealStyle;
public bool UseRevealStyle
{
get => _useRevealStyle;
set
{
_useRevealStyle = value;
if (_useRevealStyle)
{
PasswordBox.Style = (Style)PasswordBox.FindResource("MaterialDesignFloatingHintRevealPasswordBox");
}
else
{
PasswordBox.ClearValue(StyleProperty);
}

}
}

public BoundPasswordBox()
{
DataContext = new BoundPasswordBoxViewModel();
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using CommunityToolkit.Mvvm.ComponentModel;

namespace MaterialDesignThemes.UITests.Samples.PasswordBox;

internal partial class BoundPasswordBoxViewModel : ObservableObject
{
[ObservableProperty]
private string? _password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Window x:Class="MaterialDesignThemes.UITests.Samples.PasswordBox.BoundPasswordBoxWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MaterialDesignThemes.UITests.Samples.PasswordBox"
mc:Ignorable="d"
Title="BoundPasswordBoxWindow" Height="450" Width="800">
<local:BoundPasswordBox />
</Window>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MaterialDesignThemes.UITests.Samples.PasswordBox;

public partial class BoundPasswordBoxWindow
{
public BoundPasswordBoxWindow() => InitializeComponent();
}
2 changes: 1 addition & 1 deletion MaterialDesignThemes.UITests/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected async Task<IVisualElement> LoadUserControl<TControl>()
public async Task InitializeAsync() =>
App = await XamlTest.App.StartRemote(new AppOptions
{
AllowVisualStudioDebuggerAttach = true,
AllowVisualStudioDebuggerAttach = false,
LogMessage = message => Output.WriteLine(message)
});
public async Task DisposeAsync() => await App.DisposeAsync();
Expand Down
87 changes: 57 additions & 30 deletions MaterialDesignThemes.UITests/WPF/PasswordBoxes/PasswordBoxTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.ComponentModel;
using MaterialDesignThemes.UITests.Samples.PasswordBox;

namespace MaterialDesignThemes.UITests.WPF.PasswordBoxes
{
Expand Down Expand Up @@ -83,42 +84,36 @@ await Wait.For(async () =>
}

[Fact]
[Description("PR 2828")]
[Description("PR 2828 and Issue 2930")]
public async Task RevealPasswordBox_WithBoundPasswordProperty_RespectsThreeWayBinding()
{
await using var recorder = new TestRecorder(App);

var grid = await LoadXaml<Grid>(@"
<Grid Margin=""30"">
<StackPanel Orientation=""Vertical"">
<TextBox x:Name=""BoundPassword"" />
<PasswordBox x:Name=""PasswordBox""
materialDesign:PasswordBoxAssist.Password=""{Binding ElementName=BoundPassword, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}""
Style=""{StaticResource MaterialDesignFloatingHintRevealPasswordBox}""/>
</StackPanel>
</Grid>");
var boundPasswordTextBox = await grid.GetElement<TextBox>("BoundPassword"); // Serves as the "VM" in this test
var passwordBox = await grid.GetElement<PasswordBox>("PasswordBox");
await App.InitializeWithMaterialDesign();
IWindow window = await App.CreateWindow<BoundPasswordBoxWindow>();
var userControl = await window.GetElement<BoundPasswordBox>();
await userControl.SetProperty(nameof(BoundPasswordBox.UseRevealStyle), true);
var passwordBox = await userControl.GetElement<PasswordBox>("PasswordBox");
var clearTextPasswordTextBox = await passwordBox.GetElement<TextBox>("RevealPasswordTextBox");
var revealPasswordButton = await passwordBox.GetElement<ToggleButton>("RevealPasswordButton");

// Act 1 (Update in VM updates PasswordBox and RevealPasswordTextBox)
await boundPasswordTextBox.SendKeyboardInput($"1");
string? boundText1 = await boundPasswordTextBox.GetProperty<string>(TextBox.TextProperty);
// Act 1 (Update in PasswordBox updates VM and RevealPasswordTextBox)
await passwordBox.SendKeyboardInput($"1");
string? boundText1 = await userControl.GetProperty<string>(nameof(BoundPasswordBox.ViewModelPassword));
string? password1 = await passwordBox.GetProperty<string>(nameof(PasswordBox.Password));
string? clearTextPassword1 = await clearTextPasswordTextBox.GetProperty<string>(TextBox.TextProperty);

// Act 2 (Update in PasswordBox updates VM and RevealPasswordTextBox)
await passwordBox.SendKeyboardInput($"2");
string? boundText2 = await boundPasswordTextBox.GetProperty<string>(TextBox.TextProperty);
string? password2 = await passwordBox.GetProperty<string>(nameof(PasswordBox.Password));
string? clearTextPassword2 = await clearTextPasswordTextBox.GetProperty<string>(TextBox.TextProperty);

// Act 2 (Update in RevealPasswordTextBox updates PasswordBox and VM)
await revealPasswordButton.LeftClick();
await Task.Delay(50); // Wait for the "clear text TextBox" to become visible
await clearTextPasswordTextBox.SendKeyboardInput($"3");
string? boundText3 = await boundPasswordTextBox.GetProperty<string>(TextBox.TextProperty);
await clearTextPasswordTextBox.SendKeyboardInput($"2");
string? boundText2 = await userControl.GetProperty<string>(nameof(BoundPasswordBox.ViewModelPassword));
string? password2 = await passwordBox.GetProperty<string>(nameof(PasswordBox.Password));
string? clearTextPassword2 = await clearTextPasswordTextBox.GetProperty<string>(TextBox.TextProperty);

// Act 3 (Update in VM updates PasswordBox and RevealPasswordTextBox)
await userControl.SetProperty(nameof(BoundPasswordBox.ViewModelPassword), "3");
string? boundText3 = await userControl.GetProperty<string>(nameof(BoundPasswordBox.ViewModelPassword));
string? password3 = await passwordBox.GetProperty<string>(nameof(PasswordBox.Password));
string? clearTextPassword3 = await clearTextPasswordTextBox.GetProperty<string>(TextBox.TextProperty);

Expand All @@ -127,13 +122,45 @@ public async Task RevealPasswordBox_WithBoundPasswordProperty_RespectsThreeWayBi
Assert.Equal("1", password1);
Assert.Equal("1", clearTextPassword1);

Assert.Equal("21", boundText2);
Assert.Equal("21", password2);
Assert.Equal("21", clearTextPassword2);
Assert.Equal("12", boundText2);
Assert.Equal("12", password2);
Assert.Equal("12", clearTextPassword2);

Assert.Equal("3", boundText3);
Assert.Equal("3", password3);
Assert.Equal("3", clearTextPassword3);

recorder.Success();
}

[Fact]
[Description("Issue 2930")]
public async Task PasswordBox_WithBoundPasswordProperty_RespectsBinding()
{
await using var recorder = new TestRecorder(App);

await App.InitializeWithMaterialDesign();
IWindow window = await App.CreateWindow<BoundPasswordBoxWindow>();
var userControl = await window.GetElement<BoundPasswordBox>();
await userControl.SetProperty(nameof(BoundPasswordBox.UseRevealStyle), false);
var passwordBox = await userControl.GetElement<PasswordBox>("PasswordBox");

// Act 1 (Update in PasswordBox updates VM)
await passwordBox.SendKeyboardInput($"1");
string? boundText1 = await userControl.GetProperty<string>(nameof(BoundPasswordBox.ViewModelPassword));
string? password1 = await passwordBox.GetProperty<string>(nameof(PasswordBox.Password));

// Act 2 (Update in VM updates PasswordBox)
await userControl.SetProperty(nameof(BoundPasswordBox.ViewModelPassword), "2");
string? boundText2 = await userControl.GetProperty<string>(nameof(BoundPasswordBox.ViewModelPassword));
string? password2 = await passwordBox.GetProperty<string>(nameof(PasswordBox.Password));

// Assert
Assert.Equal("1", boundText1);
Assert.Equal("1", password1);

Assert.Equal("321", boundText3);
Assert.Equal("321", password3);
Assert.Equal("321", clearTextPassword3);
Assert.Equal("2", boundText2);
Assert.Equal("2", password2);

recorder.Success();
}
Expand Down