Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SampleTodoListTests #117

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 7 additions & 2 deletions src/Avalonia.Samples/Avalonia.Samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RectPainter", "Drawing\Rect
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnowflakesControlSample", "CustomControls\SnowflakesControlSample\SnowflakesControlSample.csproj", "{B7B246E1-26F7-4225-A8FC-4344C1D7BA17}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleToDoListTests", "CompleteApps\SimpleToDoListTests\SimpleToDoListTests.csproj", "{48320694-0277-45E1-9039-00A19F053171}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -143,6 +145,10 @@ Global
{B7B246E1-26F7-4225-A8FC-4344C1D7BA17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7B246E1-26F7-4225-A8FC-4344C1D7BA17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7B246E1-26F7-4225-A8FC-4344C1D7BA17}.Release|Any CPU.Build.0 = Release|Any CPU
{48320694-0277-45E1-9039-00A19F053171}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48320694-0277-45E1-9039-00A19F053171}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48320694-0277-45E1-9039-00A19F053171}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48320694-0277-45E1-9039-00A19F053171}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -164,11 +170,10 @@ Global
{B8CB5C57-07ED-4BC6-ACE8-F05E428E3EB5} = {85B157B3-F701-4F75-B4F1-EC2287729480}
{BDA7536E-26FD-436F-AAC8-F8A2B500548E} = {85B157B3-F701-4F75-B4F1-EC2287729480}
{F5CB3DA2-EB59-4792-A1B3-49F600F7C130} = {85B157B3-F701-4F75-B4F1-EC2287729480}
{48432457-6A55-4D03-9D40-260CE8E06440} = {2E99F15F-A82A-4734-A837-C0F768702600}
{0BC90E92-D8B3-4C6D-8C47-BAF57CD73CBA} = {2E99F15F-A82A-4734-A837-C0F768702600}
{7D75B38A-304C-44DE-AC2F-8A461C7FC889} = {50FCF785-BBCF-4AFE-AC72-79EA9E92C43A}
{2B746401-384F-484A-810E-7A65288165E0} = {D02161B3-8242-4BF5-96E9-780465A5023B}
{B7B246E1-26F7-4225-A8FC-4344C1D7BA17} = {92C71AA7-E791-40C0-9F3A-2A85880B0439}
{48320694-0277-45E1-9039-00A19F053171} = {50FCF785-BBCF-4AFE-AC72-79EA9E92C43A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C246CAB0-0837-4EE4-A22D-28B3C74930B4}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>


<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.5"/>
<PackageReference Include="Avalonia.Desktop" Version="11.0.5"/>
Expand All @@ -22,4 +21,9 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5"/>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" />
</ItemGroup>

<ItemGroup>
<!-- We need it so tests can use generated controls by name -->
<InternalsVisibleTo Include="SimpleToDoListTests" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@
</ScrollViewer>

<!-- This TextBox can be used to add new ToDoItems -->
<TextBox Grid.Row="2"
<TextBox Name="ItemInput" Grid.Row="2"
Text="{Binding NewItemContent}"
Watermark="Add a new Item">
<TextBox.InnerRightContent>
<Button Command="{Binding AddItemCommand}">
<Button Name="ItemAddButton" Command="{Binding AddItemCommand}">
<PathIcon Data="{DynamicResource AcceptIconData}"
Foreground="Green" />
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using global::Avalonia.Headless;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
using static Microsoft.ApplicationInsights.MetricDimensionNames.TelemetryContext;

namespace Avalonia.Headless.MSTest;

//
// Zusammenfassung:
// Identifies a nunit test that starts on Avalonia Dispatcher such that awaited
// expressions resume on the test's "main thread".
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
public sealed class AvaloniaTestMethodAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
using var _session = HeadlessUnitTestSession.GetOrStartForAssembly(testMethod?.MethodInfo.DeclaringType?.Assembly);
{
return _session.Dispatch(() => ExecuteTestMethod(testMethod), default).GetAwaiter().GetResult();
}
}

// Unfortunately, NUnit has issues with custom synchronization contexts, which means we need to add some hacks to make it work.
private async Task<TestResult[]> ExecuteTestMethod(ITestMethod testMethod)
{
return [testMethod.Invoke(null)];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleToDoList.Tests;

[TestClass()]
public class ProgramTests
{
[TestMethod()]
public void BuildAvaloniaAppTest()
{
var app = Program.BuildAvaloniaApp();

Assert.IsNotNull(app);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using SimpleToDoList.Models;

namespace SimpleToDoList.Services.Tests;

[TestClass()]
public class ToDoListFileServiceTests
{
// The path to the file we are going to test
private string destPath;

[TestInitialize]
public void TestInitialize()
{
destPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"Avalonia.SimpleToDoList", "MyToDoList.txt");

// Move a file if it exists to a backup file
if (File.Exists(destPath))
{
File.Move(destPath, Path.ChangeExtension(destPath, ".txorg"));
}
}

[TestCleanup]
public void TestCleanup()
{
// Delete the file we created
if (File.Exists(destPath))
{
File.Delete(destPath);
}

// Move the backup file back
if (File.Exists(Path.ChangeExtension(destPath, ".txorg")))
{
File.Move(Path.ChangeExtension(destPath, ".txorg"),destPath);
}
}


[DataTestMethod()]
[DataRow(new[] { "Hello World" }, new[] { true }, "[{\"IsChecked\":true,\"Content\":\"Hello World\"}]")]
[DataRow(new[] { "Get up", "Do chores" }, new[] { true, false }, "[{\"IsChecked\":true,\"Content\":\"Get up\"},{\"IsChecked\":false,\"Content\":\"Do chores\"}]")]
public void SaveToFileAsyncTest(string[] sAct, bool[] xAct, string sExp)
{
// Arrange
var items = sAct.Zip(xAct, (s, x) => new ToDoItem { Content = s, IsChecked = x });

// Act
Task t = ToDoListFileService.SaveToFileAsync(items);
t.Wait();

// Assert
Assert.IsTrue(File.Exists(destPath));
Assert.AreEqual(sExp, File.ReadAllText(destPath));
}

[DataTestMethod()]
[DataRow(new[] { "Hello World" }, new[] { true }, "[{\"IsChecked\":true,\"Content\":\"Hello World\"}]")]
[DataRow(new[] { "Get up", "Do chores" }, new[] { true, false }, "[{\"IsChecked\":true,\"Content\":\"Get up\"},{\"IsChecked\":false,\"Content\":\"Do chores\"}]")]
public void LoadFromFileAsyncTest(string[] sExp, bool[] xExp, string sAct)
{
// Arrange
File.WriteAllText(destPath, sAct);

// Act
Task<IEnumerable<ToDoItem>?> t = ToDoListFileService.LoadFromFileAsync();
t.Wait();

// Assert
Assert.IsNotNull(t.Result);
var items = t.Result;
Assert.AreEqual(sExp.Length, items.Count());
for (int i = 0; i < sExp.Length; i++)
{
Assert.AreEqual(sExp[i], items.ElementAt(i).Content);
Assert.AreEqual(xExp[i], items.ElementAt(i).IsChecked);
}
}

[TestMethod()]
public void LoadFromFileAsyncTest2()
{
// Act
Task<IEnumerable<ToDoItem>?> t = ToDoListFileService.LoadFromFileAsync();
t.Wait();

// Assert
Assert.IsNull(t.Result);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia.Headless" Version="11.2.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="MSTest" Version="3.7.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SimpleToDoList\SimpleToDoList.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// ***********************************************************************
// Assembly : SimpleToDoListTests
// Author : Joe Care
// Created : 01-12-2025
//
// Last Modified By : Joe Care
// Last Modified On : 01-12-2025
// ***********************************************************************
// <copyright file="TestAppBuilder.cs" company="SimpleToDoListTests">
// Copyright (c) .... All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using Avalonia;
using Avalonia.Headless;
using SimpleToDoList;

/// <summary>
/// Class TestAppBuilder.
/// </summary>
[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]

public class TestAppBuilder
{
/// <summary>
/// Builds the avalonia application.
/// </summary>
/// <returns>AppBuilder.</returns>
public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure<App>()
.UseHeadless(new AvaloniaHeadlessPlatformOptions());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using Avalonia.Controls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SimpleToDoList.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleToDoList.ViewModels.Tests;

[TestClass()]
public class MainViewModelTests
{
#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
private MainViewModel testModel;
private MainViewModel testModel2;
#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
private string sTestLog = "";
private bool xDesignMode;

[TestInitialize()]
public void TestInitialize()
{
testModel = new MainViewModel();
testModel.PropertyChanged += (object? sender, PropertyChangedEventArgs e)
=> DoLog($"PropChg(Sender: {sender?.GetType().Name}, Prop: {e.PropertyName}), Value = ${sender?.GetType().GetProperty(e.PropertyName ?? "")?.GetValue(sender)}");
testModel.AddItemCommand.CanExecuteChanged += (object? sender, EventArgs e)
=> DoLog($"CmdChg(Sender: {sender?.GetType().Name}) = {sender?.GetType().GetMethod("CanExecute")!.Invoke(sender,[null])}");
sTestLog = "";
xDesignMode = Design.IsDesignMode;
typeof(Design).GetProperty("IsDesignMode")!.SetValue(null, true);
testModel2 = new MainViewModel();
}

[TestCleanup]
public void TestCleanup()
{
typeof(Design).GetProperty("IsDesignMode")!.SetValue(null, xDesignMode);
}

private void DoLog(string v)
{
sTestLog += $"{v}\r\n"; // !! Fixed NewLine-Sequence
}

[TestMethod()]
public void SetUpTest()
{
Assert.IsNotNull(testModel);
Assert.IsNotNull(testModel2);
Assert.IsInstanceOfType(testModel, typeof(MainViewModel));
Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged));
Assert.IsInstanceOfType(testModel2, typeof(MainViewModel));
Assert.IsInstanceOfType(testModel2, typeof(INotifyPropertyChanged));
Assert.IsNotNull(testModel.ToDoItems);
Assert.IsNotNull(testModel2.ToDoItems);
Assert.AreEqual(0, testModel.ToDoItems.Count);
Assert.AreEqual(2,testModel2.ToDoItems.Count);
}

[DataTestMethod()]
[DataRow(new string[0], "")]
[DataRow(new[]{ "Test" }, @"PropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $Test\r\nCmdChg(Sender: RelayCommand) = True\r\n")]
[DataRow(new[]{ "Test2", null },@"PropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $Test2\r\nCmdChg(Sender: RelayCommand) = True\r\nPropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $\r\nCmdChg(Sender: RelayCommand) = False\r\n")]
[DataRow(new[]{ null, "Test3" }, @"PropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $Test3\r\nCmdChg(Sender: RelayCommand) = True\r\n")]
public void SetNewItemTest(string?[] asAct,string sExp)
{
// Act
foreach (string? s in asAct)
{
testModel.NewItemContent = s;
}

// Assert
Assert.AreEqual(sExp.Replace("\\r\\n","\r\n"), sTestLog);
}

[DataTestMethod()]
[DataRow("Test", 1, @"PropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $Test\r\nCmdChg(Sender: RelayCommand) = True\r\nPropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $\r\nCmdChg(Sender: RelayCommand) = False\r\n")]
[DataRow("",0, "PropChg(Sender: MainViewModel, Prop: NewItemContent), Value = $\\r\\nCmdChg(Sender: RelayCommand) = False\\r\\n")]
public void AddItemTest(string sAct,int iExp,string sExp)
{
// Arrange
testModel.NewItemContent = sAct;
// Act
if (testModel.AddItemCommand.CanExecute(null))
testModel.AddItemCommand.Execute(null);

// Assert
Assert.AreEqual(iExp, testModel.ToDoItems.Count);
if (iExp >0)
Assert.AreEqual(sAct, testModel.ToDoItems[0].Content);
Assert.AreEqual(iExp > 0?null:sAct, testModel.NewItemContent);
Assert.AreEqual( sExp.Replace("\\r\\n", "\r\n"), sTestLog);
}

[DataTestMethod()]
[DataRow(new[] { "Test", "Test2" }, "Test" )]
[DataRow(new[] { "Test", "Test2" }, "Test2" )]
public void RemoveItemTest(string[] sAct, string sAct2)
{
// Arrange
foreach (string s in sAct)
{
testModel.ToDoItems.Add(new() {IsChecked =false,Content = s });
}
var _act2 = testModel.ToDoItems.First(s=>s.Content==sAct2);

// Act
if (testModel.RemoveItemCommand.CanExecute(_act2))
testModel.RemoveItemCommand.Execute(_act2);

// Assert
Assert.AreEqual(sAct.Length-1, testModel.ToDoItems.Count);
Assert.AreEqual("", sTestLog);
}

}
Loading