< Summary

Line coverage
97%
Covered lines: 91
Uncovered lines: 2
Coverable lines: 93
Total lines: 182
Line coverage: 97.8%
Branch coverage
93%
Covered branches: 15
Total branches: 16
Branch coverage: 93.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: !XamlIlPopulate(...)100%22100%
File 2: .ctor()100%11100%
File 2: OnUnlockClick(...)100%4490%
File 2: OnSetupClick(...)83.33%6692.3%
File 2: CreateSecureString(...)100%44100%

File(s)

/home/runner/work/LOCKnet/LOCKnet/src/LOCKnet.App/Views/LoginView.axaml

#LineLine coverage
 61<UserControl xmlns="https://github.com/avaloniaui"
 2             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 3             xmlns:vm="using:LOCKnet.App.ViewModels"
 4             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6             mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="600"
 7             x:Class="LOCKnet.App.Views.LoginView"
 8             x:DataType="vm:LoginViewModel"
 39             Background="{StaticResource BrushBg}">
 10
 11    <Design.DataContext>
 12        <vm:LoginViewModel/>
 13    </Design.DataContext>
 14
 915    <Grid RowDefinitions="*,Auto,*">
 16        <!-- Footer credit -->
 1517        <StackPanel Grid.Row="2"
 18                    HorizontalAlignment="Center"
 319                    VerticalAlignment="Bottom"
 20                    Margin="0,0,0,20"
 321                    Spacing="2">
 1222            <TextBlock Text="Alhasan Ramadan"
 23                       FontSize="11"
 324                       Foreground="{StaticResource BrushTextMuted}"
 25                       HorizontalAlignment="Center"/>
 1226            <TextBlock Text="https://github.com/alhasan-ramadan/LOCKnet"
 27                       FontSize="11"
 328                       Foreground="{StaticResource BrushAccent}"
 29                       HorizontalAlignment="Center"/>
 30        </StackPanel>
 1231        <StackPanel Grid.Row="1"
 32                    Width="400"
 333                    HorizontalAlignment="Center"
 34                    Spacing="0">
 35
 36            <!-- Logo / Title -->
 1237            <StackPanel Orientation="Horizontal"
 38                        HorizontalAlignment="Center"
 339                        Spacing="10"
 40                        Margin="0,0,0,8">
 1241                <Image Source="/Assets/favicon-32x32.png"
 342                       Width="40" Height="40"
 43                       VerticalAlignment="Center"/>
 1244                <TextBlock Text="LOCKnet"
 45                           FontSize="34"
 346                           FontWeight="Bold"
 347                           Foreground="{StaticResource BrushTextPrimary}"
 48                           VerticalAlignment="Center"/>
 49            </StackPanel>
 1250            <TextBlock Text="Local Offline Credential Keeper"
 51                       FontSize="13"
 352                       Foreground="{StaticResource BrushTextSecondary}"
 53                       HorizontalAlignment="Center"
 354                       Margin="0,0,0,44"/>
 55
 1256            <Separator Background="{StaticResource BrushBorder}" Height="1" Margin="0,0,0,32"/>
 57
 58            <!-- Card -->
 959            <Border Background="{StaticResource BrushSurface}"
 360                    CornerRadius="{StaticResource RadiusLg}"
 61                    Padding="40,36">
 962                <StackPanel Spacing="20">
 63
 64                    <!-- Mode heading -->
 965                    <TextBlock Text="Ersteinrichtung"
 66                               FontSize="18"
 367                               FontWeight="SemiBold"
 368                               Foreground="{StaticResource BrushTextPrimary}"
 369                               IsVisible="{Binding IsSetupMode}"/>
 970                    <TextBlock Text="Willkommen zurück"
 71                               FontSize="18"
 372                               FontWeight="SemiBold"
 373                               Foreground="{StaticResource BrushTextPrimary}"
 374                               IsVisible="{Binding !IsSetupMode}"/>
 75
 76                    <!-- Password -->
 977                    <StackPanel Spacing="6">
 978                        <TextBlock Text="Master-Passwort"
 79                                   FontSize="12"
 380                                   Foreground="{StaticResource BrushTextSecondary}"/>
 981                        <TextBox x:Name="PasswordInput"
 82                                 PasswordChar="●"
 383                                 Watermark="Passwort eingeben…"/>
 84                    </StackPanel>
 85
 86                    <!-- Confirm Password (only setup mode) -->
 1287                    <StackPanel Spacing="6" IsVisible="{Binding IsSetupMode}">
 988                        <TextBlock Text="Passwort bestätigen"
 89                                   FontSize="12"
 390                                   Foreground="{StaticResource BrushTextSecondary}"/>
 991                        <TextBox x:Name="ConfirmPasswordInput"
 92                                 PasswordChar="●"
 393                                 Watermark="Passwort wiederholen…"/>
 94                    </StackPanel>
 95
 96                    <!-- Error -->
 997                    <TextBlock Text="{Binding ErrorMessage}"
 398                               Foreground="{StaticResource BrushError}"
 99                               FontSize="12"
 3100                               TextWrapping="Wrap"
 3101                               IsVisible="{Binding ErrorMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}
 102
 103                    <!-- Buttons -->
 12104                    <Button Content="Entsperren"
 105                            Classes="primary"
 3106                            Click="OnUnlockClick"
 3107                            IsVisible="{Binding !IsSetupMode}"
 108                            HorizontalAlignment="Stretch"
 3109                            HorizontalContentAlignment="Center"/>
 110
 12111                    <Button Content="Einrichten &amp; Entsperren"
 112                            Classes="primary"
 3113                            Click="OnSetupClick"
 3114                            IsVisible="{Binding IsSetupMode}"
 115                            HorizontalAlignment="Stretch"
 3116                            HorizontalContentAlignment="Center"/>
 117
 118                </StackPanel>
 119            </Border>
 120
 121        </StackPanel>
 122    </Grid>
 123
 124</UserControl>

/home/runner/work/LOCKnet/LOCKnet/src/LOCKnet.App/Views/LoginView.axaml.cs

#LineLine coverage
 1using Avalonia.Controls;
 2using Avalonia.Interactivity;
 3using LOCKnet.App.ViewModels;
 4using System.Security;
 5
 6namespace LOCKnet.App.Views;
 7
 8public partial class LoginView : UserControl
 9{
 310  public LoginView()
 311  {
 312    InitializeComponent();
 313  }
 14
 15  private void OnUnlockClick(object? sender, RoutedEventArgs e)
 216  {
 217    if (DataContext is not LoginViewModel vm)
 118      return;
 19
 120    var passwordInput = this.FindControl<TextBox>("PasswordInput");
 121    if (passwordInput is null)
 022      return;
 23
 124    using var password = CreateSecureString(passwordInput.Text);
 125    vm.Unlock(password);
 126    passwordInput.Text = string.Empty;
 327  }
 28
 29  private void OnSetupClick(object? sender, RoutedEventArgs e)
 230  {
 231    if (DataContext is not LoginViewModel vm)
 132      return;
 33
 134    var passwordInput = this.FindControl<TextBox>("PasswordInput");
 135    var confirmPasswordInput = this.FindControl<TextBox>("ConfirmPasswordInput");
 136    if (passwordInput is null || confirmPasswordInput is null)
 037      return;
 38
 139    using var password = CreateSecureString(passwordInput.Text);
 140    using var confirmPassword = CreateSecureString(confirmPasswordInput.Text);
 141    vm.Setup(password, confirmPassword);
 142    passwordInput.Text = string.Empty;
 143    confirmPasswordInput.Text = string.Empty;
 344  }
 45
 46  private static SecureString CreateSecureString(string? value)
 347  {
 348    var secure = new SecureString();
 349    if (!string.IsNullOrEmpty(value))
 350    {
 5151      foreach (var c in value)
 2152        secure.AppendChar(c);
 353    }
 54
 355    secure.MakeReadOnly();
 356    return secure;
 357  }
 58}