* added page style for theme switching

* new test branch

* added test files

* templatized namespaces

* namespace + test project csproj file

* mock services

* usings.cs fix, tests running

* test file fixes + post action

* csproj fix to make post action unnecessary

* nits

* New file structure, composition template working but file not being added in correct place

* simplified for dev, template working (not including multiple instances)

* templatized view model tests + mocks

* file removed

* removed shell view model

* removed shell view model tests

* Resolved merge conflict in the csproj.

* testing added to context menu

* Renamed SplitView to NavView.

* renamed AddContentGrid to AddCGrid

* csproj change

* Removed unnecessary files and fixed bug in PrimaryOutputs.

* renamed test post action folders

* Updated MockWebViewService.

* Updated MockLocalSettingsService.

* Fixed line spacing issue.

* Added missing using statement.

* removed mocks + changed template for main view model tests

* removed test file post actions, created new folder for packaged testing post action, added readme into test project

* csproj fix

* post action for packaged project with tests (not working yet)

* removed post action + added to readme

* -

* changed wording

* -

* fixed readme encoding + csproj issue

* Removed redundant entries in the csproj and fixed typo.

* Updated README.md and added TODO: comment and Assert in TestMethod1.

* Updated test code.

* fixed test project package reference versions

* x64 fix

* x86, x64, & arm64

* Added support for PRI files.

* Removed unnecessary test certificate.

* Moved DataGrid sample to README.md.

* Fixed namespace bug.

* merged packaged & unpackaged versions of localsettingservice
localsettingservice now conditionalized

* template fix

* Revert "template fix"

This reverts commit 1f3d2fee2c.

* settings storage template fix

* template fix 2

* Added MSIX conditionals in LocalSettingsService and GetVersionDescription.

Fixed #4555.

* Call Bootstrap.TryInitialize in AssemblyInitialize. Add other Initialize and Cleanup stubs.

This is required when testing MSIX apps that are framework-dependent on the Windows App SDK.

* Fixed test failures.

* Updated README.md.

* Updated sample test code.

* Added localization.

* Renamed README.txt.

* Updated Core README.md.

* Fixed encoding issues.

* Set utf-8-bom in .editorconfig for JSON and MD files to avoid encoding issues.

Co-authored-by: Sophia Morin <t-smorin@microsoft.com>
Co-authored-by: Mike Battista <13860912+mikebattista@users.noreply.github.com>
This commit is contained in:
Sophia Morin 2022-07-18 22:03:30 -07:00 коммит произвёл GitHub
Родитель fb3557a2f2
Коммит c5053bfdd0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
28 изменённых файлов: 385 добавлений и 193 удалений

Просмотреть файл

@ -175,6 +175,14 @@ csharp_style_prefer_method_group_conversion = true:silent
curly_bracket_next_line = true
indent_brace_style = Allman
# JSON files
[*.json]
charset = utf-8-bom
# MD files
[*.md]
charset = utf-8-bom
# xaml files
[*.xaml]
charset = utf-8-bom

Просмотреть файл

@ -31,7 +31,7 @@ namespace Microsoft.Templates.UI.VisualStudio
new RightClickAvailability(Platforms.Uwp, ProgrammingLanguages.CSharp) { TemplateTypes = new List<TemplateType>() { TemplateType.Page, TemplateType.Feature, TemplateType.Service, TemplateType.Testing } },
new RightClickAvailability(Platforms.Uwp, ProgrammingLanguages.VisualBasic) { TemplateTypes = new List<TemplateType>() { TemplateType.Page, TemplateType.Feature, TemplateType.Service, TemplateType.Testing } },
new RightClickAvailability(Platforms.Wpf, ProgrammingLanguages.CSharp) { TemplateTypes = new List<TemplateType>() { TemplateType.Page, TemplateType.Feature, TemplateType.Testing } },
new RightClickAvailability(Platforms.WinUI, ProgrammingLanguages.CSharp, AppModels.Desktop) { TemplateTypes = new List<TemplateType>() { TemplateType.Page, TemplateType.Feature } },
new RightClickAvailability(Platforms.WinUI, ProgrammingLanguages.CSharp, AppModels.Desktop) { TemplateTypes = new List<TemplateType>() { TemplateType.Page, TemplateType.Feature, TemplateType.Testing } },
};
private readonly GenerationService _generationService = GenerationService.Instance;

Просмотреть файл

@ -179,6 +179,9 @@
<Content Include="Templates\Proj\Default\Param_ProjectName\Assets\WindowIcon.ico">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\Param_ProjectName.Tests.MSTest\UnitTest1.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Project.NavView.AddNavViewItem.WebView\Views\ShellPage_postaction.xaml">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
@ -203,6 +206,9 @@
<Content Include="Templates\Proj\Default\Param_ProjectName\MainWindow.xaml">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\.template.config\icon.xaml">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedStyles\AllStylesDictionary.cs">
@ -225,6 +231,18 @@
<DependentUpon>source.extension.vsixmanifest</DependentUpon>
</Compile>
<Compile Include="TemplateStudioForWinUICsPackage.cs" />
<Content Include="Templates\Test\App.MSTest\Param_ProjectName.Tests.MSTest\Initialize.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\Param_ProjectName.Tests.MSTest\Usings.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName\Helpers\RuntimeHelper.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Ft\SettingsStorage\Param_ProjectName\Services\LocalSettingsService.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName\MainWindow.xaml.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
@ -259,6 +277,15 @@
<Content Include="Templates\Ft\AppNotifications\.template.config\localize\description.md">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\Param_ProjectName.Tests.MSTest\README.md">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\.template.config\localize\templatestrings.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName.Core\README.md">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<VSCTCompile Include="Commands\TemplateStudioForWinuiPackage.vsct">
<Generator>VsctGenerator</Generator>
<ResourceName>Menus.ctmenu</ResourceName>
@ -386,6 +413,17 @@
<Content Include="Templates\_comp\_shared\Page.AddBackground.Blank\.template.config\template.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\.template.config\localize\description.md">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\.template.config\template.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Test\App.MSTest\Param_ProjectName.Tests.MSTest\Param_ProjectName.Tests.MSTest.csproj">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Templates\Ft\MSIX\.template.config\localize\templatestrings.it-IT.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
@ -2105,9 +2143,6 @@
<Content Include="Templates\_comp\_shared\Proj.Core.Platforms\Param_ProjectName.Core\Param_ProjectName.Core_postaction.csproj">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName.Core\README.txt">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName\TemplateStudio.xml">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
@ -2252,31 +2287,16 @@
<Content Include="Templates\Ft\SettingsStorage\Param_ProjectName\Models\LocalSettingsOptions.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Ft\SettingsStorage\Param_ProjectName\Services\LocalSettingsServicePackaged.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Ft\SettingsStorage\Param_ProjectName\Services\LocalSettingsServiceUnpackaged.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName.Core\Contracts\Services\IFileService.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName.Core\Services\FileService.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Page.Settings.Packaged\ViewModels\Param_ItemNameViewModel_postaction.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Page.Settings.Unpackaged\ViewModels\Param_ItemNameViewModel_postaction.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Project.NavView\Helpers\NavigationHelper.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Feature.SettingsStorage.Packaged\App_postaction.xaml.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Feature.SettingsStorage.Unpackaged\App_postaction.xaml.cs">
<Content Include="Templates\_comp\MT\Feature.SettingsStorage\App_postaction.xaml.cs">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Ft\MSIX\Param_ProjectName_postaction.csproj">
@ -2291,23 +2311,13 @@
<Content Include="Templates\Ft\SettingsStorage\Param_ProjectName\Param_ProjectName_postaction.csproj">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Feature.SettingsStorage.Packaged\.template.config\template.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Feature.SettingsStorage.Unpackaged\.template.config\template.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Page.Settings.Packaged\.template.config\template.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\_comp\MT\Page.Settings.Unpackaged\.template.config\template.json">
<Content Include="Templates\_comp\MT\Feature.SettingsStorage\.template.config\template.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="Templates\Proj\Default\Param_ProjectName\Properties\launchsettings.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
<ItemGroup />
<Import Project="..\SharedFunctionality.Core\SharedFunctionality.Core.projitems" Label="Shared" />
<Import Project="..\SharedFunctionality.UI\SharedFunctionality.UI.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Просмотреть файл

@ -43,10 +43,7 @@
"path": "Param_ProjectName/Models/LocalSettingsOptions.cs"
},
{
"path": "Param_ProjectName/Services/LocalSettingsServicePackaged.cs"
},
{
"path": "Param_ProjectName/Services/LocalSettingsServiceUnpackaged.cs"
"path": "Param_ProjectName/Services/LocalSettingsService.cs"
}
],
"symbols": {

Просмотреть файл

@ -1,12 +1,16 @@
using Param_RootNamespace.Contracts.Services;
using Param_RootNamespace.Core.Contracts.Services;
using Param_RootNamespace.Core.Helpers;
using Param_RootNamespace.Helpers;
using Param_RootNamespace.Models;
using Microsoft.Extensions.Options;
using Windows.ApplicationModel;
using Windows.Storage;
namespace Param_RootNamespace.Services;
public class LocalSettingsServiceUnpackaged : ILocalSettingsService
public class LocalSettingsService : ILocalSettingsService
{
private const string _defaultApplicationDataFolder = "Param_ProjectName/ApplicationData";
private const string _defaultLocalSettingsFile = "LocalSettings.json";
@ -22,7 +26,7 @@ public class LocalSettingsServiceUnpackaged : ILocalSettingsService
private bool _isInitialized;
public LocalSettingsServiceUnpackaged(IFileService fileService, IOptions<LocalSettingsOptions> options)
public LocalSettingsService(IFileService fileService, IOptions<LocalSettingsOptions> options)
{
_fileService = fileService;
_options = options.Value;
@ -45,13 +49,21 @@ public class LocalSettingsServiceUnpackaged : ILocalSettingsService
public async Task<T?> ReadSettingAsync<T>(string key)
{
await InitializeAsync();
object? obj;
if (_settings != null && _settings.TryGetValue(key, out obj))
if (RuntimeHelper.IsMSIX)
{
return await Json.ToObjectAsync<T>((string)obj);
if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
}
else
{
await InitializeAsync();
if (_settings != null && _settings.TryGetValue(key, out var obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
}
return default;
@ -59,10 +71,17 @@ public class LocalSettingsServiceUnpackaged : ILocalSettingsService
public async Task SaveSettingAsync<T>(string key, T value)
{
await InitializeAsync();
if (RuntimeHelper.IsMSIX)
{
ApplicationData.Current.LocalSettings.Values[key] = await Json.StringifyAsync(value);
}
else
{
await InitializeAsync();
_settings[key] = await Json.StringifyAsync(value);
_settings[key] = await Json.StringifyAsync(value);
await Task.Run(() => _fileService.Save(_applicationDataFolder, _localsettingsFile, _settings));
await Task.Run(() => _fileService.Save(_applicationDataFolder, _localsettingsFile, _settings));
}
}
}

Просмотреть файл

@ -1,23 +0,0 @@
using Param_RootNamespace.Contracts.Services;
using Param_RootNamespace.Core.Helpers;
using Windows.Storage;
namespace Param_RootNamespace.Services;
public class LocalSettingsServicePackaged : ILocalSettingsService
{
public async Task<T?> ReadSettingAsync<T>(string key)
{
if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj))
{
return await Json.ToObjectAsync<T>((string)obj);
}
return default;
}
public async Task SaveSettingAsync<T>(string key, T value)
{
ApplicationData.Current.LocalSettings.Values[key] = await Json.StringifyAsync(value);
}
}

Просмотреть файл

@ -1,7 +1,9 @@
using System.Windows.Input;
using System.Reflection;
using System.Windows.Input;
using Microsoft.UI.Xaml;
using Param_RootNamespace.Contracts.Services;
using Param_RootNamespace.Helpers;
using Windows.ApplicationModel;
namespace Param_RootNamespace.ViewModels;
@ -47,5 +49,19 @@ public class Param_ItemNameViewModel : System.ComponentModel.INotifyPropertyChan
private static string GetVersionDescription()
{
Version version;
if (RuntimeHelper.IsMSIX)
{
var packageVersion = Package.Current.Id.Version;
version = new(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision);
}
else
{
version = Assembly.GetExecutingAssembly().GetName().Version!;
}
return $"{"AppDisplayName".GetLocalized()} - {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
}
}

Просмотреть файл

@ -0,0 +1,5 @@
*Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)*
## Getting Started
The Core project contains code that can be [reused across multiple application projects](https://docs.microsoft.com/dotnet/standard/net-standard#net-5-and-net-standard).

Просмотреть файл

@ -1 +0,0 @@
This is a .NET Standard project which is meant to contain code that can be reused across multiple .NET implementations.

Просмотреть файл

@ -2,7 +2,7 @@
namespace Param_RootNamespace.Helpers;
internal static class ResourceExtensions
public static class ResourceExtensions
{
private static readonly ResourceLoader _resourceLoader = new();

Просмотреть файл

@ -0,0 +1,20 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Param_RootNamespace.Helpers;
public class RuntimeHelper
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder? packageFullName);
public static bool IsMSIX
{
get
{
var length = 0;
return GetCurrentPackageFullName(ref length, null) != 15700L;
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
<Canvas Width="48" Height="48">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<Canvas>
<Canvas.RenderTransform>
<MatrixTransform Matrix="0.01 0 0 -0.01 0.55901648 48.091656"/>
</Canvas.RenderTransform>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="#FF000000">
<Path.Data>
<PathGeometry Figures="m 304 1851 c 105.35564 163.8877 184.34235 289.3362 296 466 0 527.6667 0 1055.3333 0 1583 700 0 1400 0 2100 0 0 -100 0 -200 0 -300 500 0 1000 0 1500 0 0 -800 0 -1600 0 -2400 -263.6667 0 -527.3333 0 -791 0 l 20 -29 c 26 -36 29 -156 6 -221 -8 -23 -15 -44 -15 -46 380.3123 -5.9786 670.2318 -4 1080 -4 0 1200 0 2400 0 3600 -1400 0 -2800 0 -4200 0 10.68364 -882.7474 -15.11657 -1766.4517 4 -2649 z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="#FF000000">
<Path.Data>
<PathGeometry Figures="m 900 3450 v -150 h 150 150 V 2995 2691 L 689 1888 C 408 1446 173 1075 168 1064 c -8 -17 5 -68 63 -243 l 74 -221 h 1345 1345 l 73 218 c 39 120 72 223 72 229 0 7 -234 380 -520 829 l -520 818 v 303 303 h 150 150 v 150 150 H 1650 900 Z m 900 -489 v -339 l 260 -409 260 -408 -335 -3 c -184 -1 -485 -1 -669 0 l -334 3 259 407 259 407 v 341 340 h 150 150 z" FillRule="NonZero"/>
</Path.Data>
</Path>
</Canvas>
</Canvas>
</Viewbox>

Просмотреть файл

@ -0,0 +1 @@
Add an MSTest project to write unit tests.

Просмотреть файл

@ -0,0 +1,7 @@
{
"name": "MSTest",
"description": "Add an MSTest project to write unit tests.",
"_name.comment": "Label for an MSTest project.",
"_description.comment": "Label description for MSTest."
}

Просмотреть файл

@ -0,0 +1,100 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Microsoft",
"classifications": [ "Universal" ],
"name": "MSTest",
"shortName": "MSTest",
"groupIdentity": "ts.WinUI.Testing.App.MSTest",
"identity": "ts.WinUI.Testing.App.MSTest",
"description": "Add an MSTest project to write unit tests.",
"tags": {
"language": "C#",
"type": "project",
"ts.type": "testing",
"ts.projecttype": "Blank|NavView|MenuBar",
"ts.outputToParent": "true",
"ts.frontendframework": "all",
"ts.platform": "WinUI",
"ts.appmodel": "Desktop",
"ts.version": "1.0.0",
"ts.displayOrder": "1",
"ts.defaultInstance": "MSTest",
"ts.multipleInstance": "false",
"ts.genGroup": "0",
"ts.rightClickEnabled": "true"
},
"sourceName": "Param_ProjectName",
"preferNameDirectory": true,
"guids": [],
"PrimaryOutputs": [
{ "path": "Param_ProjectName.Tests.MSTest/Param_ProjectName.Tests.MSTest.csproj" }
],
"symbols": {
"ts.projectName": {
"type": "parameter",
"replaces": "Param_ProjectName",
"fileRename": "Param_ProjectName"
},
"ts.rootNamespace": {
"type": "parameter",
"replaces": "Param_RootNamespace"
}
},
"postActions": [
{
"description": "Add reference to the main WinUI app",
"manualInstructions": [],
"actionId": "849AAEB8-487D-45B3-94B9-77FA74E83A01",
"args": {
"fileIndex": "0",
"projectPath": "Param_ProjectName\\Param_ProjectName.csproj",
"specifiedPathIsTarget": "true"
},
"continueOnError": true
},
{
"description": "Add nuget package",
"manualInstructions": [],
"actionId": "0B814718-16A3-4F7F-89F1-69C0F9170EAD",
"args": {
"packageId": "Microsoft.NET.Test.Sdk",
"version": "17.1.0",
"projectPath": "Param_ProjectName.Tests.MSTest\\Param_ProjectName.Tests.MSTest.csproj"
},
"continueOnError": true
},
{
"description": "Add nuget package",
"manualInstructions": [],
"actionId": "0B814718-16A3-4F7F-89F1-69C0F9170EAD",
"args": {
"packageId": "MSTest.TestFramework",
"version": "2.2.10",
"projectPath": "Param_ProjectName.Tests.MSTest\\Param_ProjectName.Tests.MSTest.csproj"
},
"continueOnError": true
},
{
"description": "Add nuget package",
"manualInstructions": [],
"actionId": "0B814718-16A3-4F7F-89F1-69C0F9170EAD",
"args": {
"packageId": "MSTest.TestAdapter",
"version": "2.2.10",
"projectPath": "Param_ProjectName.Tests.MSTest\\Param_ProjectName.Tests.MSTest.csproj"
},
"continueOnError": true
},
{
"description": "Add nuget package",
"manualInstructions": [],
"actionId": "0B814718-16A3-4F7F-89F1-69C0F9170EAD",
"args": {
"packageId": "coverlet.collector",
"version": "3.1.2",
"projectPath": "Param_ProjectName.Tests.MSTest\\Param_ProjectName.Tests.MSTest.csproj"
},
"continueOnError": true
}
]
}

Просмотреть файл

@ -0,0 +1,21 @@
using Microsoft.Windows.ApplicationModel.DynamicDependency;
namespace Param_RootNamespace.Tests.MSTest;
[TestClass]
public class Initialize
{
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
// TODO: Initialize the appropriate version of the Windows App SDK.
// This is required when testing MSIX apps that are framework-dependent on the Windows App SDK.
Bootstrap.TryInitialize(0x00010001, out var _);
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Bootstrap.Shutdown();
}
}

Просмотреть файл

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<Platforms>x86;x64;arm64</Platforms>
<ProjectPriFileName>resources.pri</ProjectPriFileName>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,51 @@
*Recommended Markdown Viewer: [Markdown Editor](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor2)*
## Getting Started
[Get started with unit testing](https://docs.microsoft.com/visualstudio/test/getting-started-with-unit-testing?view=vs-2022&tabs=dotnet%2Cmstest), [Use the MSTest framework in unit tests](https://docs.microsoft.com/visualstudio/test/using-microsoft-visualstudio-testtools-unittesting-members-in-unit-tests), and [Run unit tests with Test Explorer](https://docs.microsoft.com/visualstudio/test/run-unit-tests-with-test-explorer) provide an overview of the MSTest framework and Test Explorer.
## Dependency Injection and Mocking
Template Studio uses [dependency injection](https://docs.microsoft.com/dotnet/core/extensions/dependency-injection) which means class dependencies implement interfaces and those dependencies are injected via class constructors.
One of the many benefits of this approach is improved testability, since tests can produce mock implementations of the interfaces and pass them into the object being tested, isolating the object being tested from its dependencies. To mock an interface, create a class that implements the interface, create stub implementations of the interface members, then pass an instance of the class into the object constructor.
## Example
The below example demonstrates testing the ViewModel for the Settings page. `SettingsViewModel` depends on `IThemeSelectorService`, so a `MockThemeSelectorService` class is introduced that implements the interface with stub implementations, and then an instance of that class is passed into the `SettingsViewModel` constructor. The `VerifyVersionDescription` test then validates that the `VersionDescription` property of the `SettingsViewModel` returns the expected value.
```csharp
// SettingsViewModelTests.cs
[TestClass]
public class SettingsViewModelTests
{
private readonly SettingsViewModel _viewModel;
public SettingsViewModelTests()
{
_viewModel = new SettingsViewModel(new MockThemeSelectorService());
}
[TestMethod]
public void VerifyVersionDescription()
{
Assert.IsTrue(Regex.IsMatch(_viewModel.VersionDescription, @"App1 - \d\.\d\.\d\.\d"));
}
}
```
```csharp
// Mocks/MockThemeSelectorService.cs
internal class MockThemeSelectorService : IThemeSelectorService
{
public ElementTheme Theme => ElementTheme.Default;
public Task InitializeAsync() => Task.CompletedTask;
public Task SetRequestedThemeAsync() => Task.CompletedTask;
public Task SetThemeAsync(ElementTheme theme) => Task.CompletedTask;
}
```

Просмотреть файл

@ -0,0 +1,42 @@
using System.Diagnostics;
namespace Param_RootNamespace.Tests.MSTest;
[TestClass]
public class UnitTest1
{
[ClassInitialize()]
public static void ClassInitialize(TestContext context)
{
Debug.WriteLine("ClassInitialize");
}
[ClassCleanup()]
public static void ClassCleanup()
{
Debug.WriteLine("ClassCleanup");
}
[TestInitialize()]
public void Initialize()
{
Debug.WriteLine("TestInitialize");
}
[TestCleanup()]
public void Cleanup()
{
Debug.WriteLine("TestCleanup");
}
[TestMethod]
public void TestMethod1()
{
// TODO: Write unit tests.
// https://docs.microsoft.com/visualstudio/test/getting-started-with-unit-testing
// https://docs.microsoft.com/visualstudio/test/using-microsoft-visualstudio-testtools-unittesting-members-in-unit-tests
// https://docs.microsoft.com/visualstudio/test/run-unit-tests-with-test-explorer
Assert.IsTrue(true);
}
}

Просмотреть файл

@ -0,0 +1 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Microsoft Community",
"classifications": [
"Universal"
],
"name": "ts.WinUI.Feat.SettingsStorage.Packaged",
"shortName": "ts.WinUI.Feat.SettingsStorage.Packaged",
"identity": "ts.WinUI.Feat.SettingsStorage.Packaged",
"tags": {
"language": "C#",
"type": "item",
"ts.type": "composition",
"ts.platform": "WinUI",
"ts.version": "1.0.0",
"ts.compositionFilter": "$frontendframework == MVVMToolkit & groupidentity == ts.WinUI.Feat.SettingsStorage & $feature == ts.WinUI.Feat.MSIXPackaging"
},
"sourceName": "Param_ItemName",
"preferNameDirectory": true,
"PrimaryOutputs": [
],
"symbols": {
"ts.rootNamespace": {
"type": "parameter",
"replaces": "Param_RootNamespace"
}
}
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Microsoft Community",
"classifications": [
"Universal"
],
"name": "ts.WinUI.Feat.SettingsStorage.Unpackaged",
"shortName": "ts.WinUI.Feat.SettingsStorage.Unpackaged",
"identity": "ts.WinUI.Feat.SettingsStorage.Unpackaged",
"tags": {
"language": "C#",
"type": "item",
"ts.type": "composition",
"ts.platform": "WinUI",
"ts.version": "1.0.0",
"ts.compositionFilter": "$frontendframework == MVVMToolkit & groupidentity == ts.WinUI.Feat.SettingsStorage & $feature != ts.WinUI.Feat.MSIXPackaging"
},
"sourceName": "Param_ItemName",
"preferNameDirectory": true,
"PrimaryOutputs": [
],
"symbols": {
"ts.rootNamespace": {
"type": "parameter",
"replaces": "Param_RootNamespace"
}
}
}

Просмотреть файл

@ -1,6 +0,0 @@
 ConfigureServices((context, services) =>
{
// Services
//{[{
services.AddSingleton<ILocalSettingsService, LocalSettingsServiceUnpackaged>();
//}]}

Просмотреть файл

@ -4,16 +4,16 @@
"classifications": [
"Universal"
],
"name": "ts.WinUI.Page.Settings.Packaged",
"shortName": "ts.WinUI.Page.Settings.Packaged",
"identity": "ts.WinUI.Page.Settings.Packaged",
"name": "ts.WinUI.MVVMToolkit.Feat.SettingsStorage",
"shortName": "ts.WinUI.MVVMToolkit.Feat.SettingsStorage",
"identity": "ts.WinUI.MVVMToolkit.Feat.SettingsStorage",
"tags": {
"language": "C#",
"type": "item",
"ts.type": "composition",
"ts.platform": "WinUI",
"ts.version": "1.0.0",
"ts.compositionFilter": "$frontendframework == MVVMToolkit & groupidentity == ts.WinUI.Page.Settings & $feature == ts.WinUI.Feat.MSIXPackaging"
"ts.compositionFilter": "$frontendframework == MVVMToolkit & groupidentity == ts.WinUI.Feat.SettingsStorage"
},
"sourceName": "Param_ItemName",
"preferNameDirectory": true,

Просмотреть файл

@ -2,5 +2,5 @@
{
// Services
//{[{
services.AddSingleton<ILocalSettingsService, LocalSettingsServicePackaged>();
services.AddSingleton<ILocalSettingsService, LocalSettingsService>();
//}]}

Просмотреть файл

@ -1,13 +0,0 @@
//{[{
using Windows.ApplicationModel;
//}]}
private static string GetVersionDescription()
{
//{[{
var appName = "AppDisplayName".GetLocalized();
var version = Package.Current.Id.Version;
return $"{appName} - {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
//}]}
}

Просмотреть файл

@ -1,28 +0,0 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Microsoft Community",
"classifications": [
"Universal"
],
"name": "ts.WinUI.Page.Settings.Unpackaged",
"shortName": "ts.WinUI.Page.Settings.Unpackaged",
"identity": "ts.WinUI.Page.Settings.Unpackaged",
"tags": {
"language": "C#",
"type": "item",
"ts.type": "composition",
"ts.platform": "WinUI",
"ts.version": "1.0.0",
"ts.compositionFilter": "$frontendframework == MVVMToolkit & groupidentity == ts.WinUI.Page.Settings & $feature != ts.WinUI.Feat.MSIXPackaging"
},
"sourceName": "Param_ItemName",
"preferNameDirectory": true,
"PrimaryOutputs": [
],
"symbols": {
"ts.rootNamespace": {
"type": "parameter",
"replaces": "Param_RootNamespace"
}
}
}

Просмотреть файл

@ -1,13 +0,0 @@
//{[{
using System.Reflection;
//}]}
private static string GetVersionDescription()
{
//{[{
var appName = "AppDisplayName".GetLocalized();
var version = Assembly.GetExecutingAssembly().GetName().Version;
return $"{appName} - {version?.Major}.{version?.Minor}.{version?.Build}.{version?.Revision}";
//}]}
}