diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests.csproj b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests.csproj new file mode 100644 index 000000000..ff9b195ac --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + + diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests/LabsUITestMethodTests.cs b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests/LabsUITestMethodTests.cs new file mode 100644 index 000000000..3656bb557 --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests/LabsUITestMethodTests.cs @@ -0,0 +1,296 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; +using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Diagnostics; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CommunityToolkit.Labs.Core.SourceGenerators.Tests; + +[TestClass] +public partial class LabsUITestMethodTests +{ + private const string DispatcherQueueDefinition = @" +namespace MyApp +{ + public partial class Test + { + public System.Threading.Tasks.Task EnqueueAsync(System.Func> function) => System.Threading.Tasks.Task.Run(function); + + public System.Threading.Tasks.Task EnqueueAsync(System.Action function) => System.Threading.Tasks.Task.Run(function); + } +} +"; + + [TestMethod] + public void TestControlHasConstructorWithParameters() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + public System.Threading.Tasks.Task LoadTestContentAsync(Microsoft.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + public System.Threading.Tasks.Task UnloadTestContentAsync(Microsoft.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + + [LabsUITestMethod] + public void TestMethod(MyControl control) + { + } + } + + public class MyControl : Microsoft.UI.Xaml.FrameworkElement + { + public MyControl(string id) + { + } + } + } + + namespace Microsoft.UI.Xaml + { + public class FrameworkElement { } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition, DiagnosticDescriptors.TestControlHasConstructorWithParameters.Id); + } + + [TestMethod] + public void Async_Mux_NoErrors() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + public System.Threading.Tasks.Task LoadTestContentAsync(Microsoft.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + public System.Threading.Tasks.Task UnloadTestContentAsync(Microsoft.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + + [LabsUITestMethod] + public async System.Threading.Tasks.Task TestMethod(MyControl control) + { + } + } + + public class MyControl : Microsoft.UI.Xaml.FrameworkElement + { + } + } + + namespace Microsoft.UI.Xaml + { + public class FrameworkElement { } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition); + } + + [TestMethod] + public void Async_Wux_NoErrors() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + public System.Threading.Tasks.Task LoadTestContentAsync(Windows.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + public System.Threading.Tasks.Task UnloadTestContentAsync(Windows.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + + [LabsUITestMethod] + public async System.Threading.Tasks.Task TestMethod(MyControl control) + { + } + } + + public class MyControl : Windows.UI.Xaml.FrameworkElement + { + } + } + + namespace Windows.UI.Xaml + { + public class FrameworkElement { } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition); + } + + [TestMethod] + public void Async_NoMethodParams_NoErrors() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + [LabsUITestMethod] + public async System.Threading.Tasks.Task TestMethod() + { + } + } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition); + } + + [TestMethod] + public void Synchronous_Mux_NoErrors() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + public System.Threading.Tasks.Task LoadTestContentAsync(Microsoft.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + public System.Threading.Tasks.Task UnloadTestContentAsync(Microsoft.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + + [LabsUITestMethod] + public void TestMethod(MyControl control) + { + } + } + + public class MyControl : Microsoft.UI.Xaml.FrameworkElement + { + } + } + + namespace Microsoft.UI.Xaml + { + public class FrameworkElement { } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition); + } + + [TestMethod] + public void Synchronous_Wux_NoErrors() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + public System.Threading.Tasks.Task LoadTestContentAsync(Windows.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + public System.Threading.Tasks.Task UnloadTestContentAsync(Windows.UI.Xaml.FrameworkElement content) => System.Threading.Tasks.Task.CompletedTask; + + [LabsUITestMethod] + public void TestMethod(MyControl control) + { + } + } + + public class MyControl : Windows.UI.Xaml.FrameworkElement + { + } + } + + namespace Windows.UI.Xaml + { + public class FrameworkElement { } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition); + } + + [TestMethod] + public void Synchronous_NoMethodParams_NoErrors() + { + string source = @" + using System.ComponentModel; + using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + + namespace MyApp + { + public partial class Test + { + [LabsUITestMethod] + public void TestMethod() + { + } + } + }"; + + VerifyGeneratedDiagnostics(source + DispatcherQueueDefinition); + } + + /// + /// Verifies the output of a source generator. + /// + /// The generator type to use. + /// The input source to process. + /// The input documentation info to process. + /// The diagnostic ids to expect for the input source code. + private static void VerifyGeneratedDiagnostics(string source, params string[] diagnosticsIds) + where TGenerator : class, IIncrementalGenerator, new() + { + VerifyGeneratedDiagnostics(CSharpSyntaxTree.ParseText(source), diagnosticsIds); + } + + /// + /// Verifies the output of a source generator. + /// + /// The generator type to use. + /// The input source tree to process. + /// The input documentation info to process. + /// The diagnostic ids to expect for the input source code. + private static void VerifyGeneratedDiagnostics(SyntaxTree syntaxTree, params string[] diagnosticsIds) + where TGenerator : class, IIncrementalGenerator, new() + { + var attributeType = typeof(LabsUITestMethodAttribute); + + var references = + from assembly in AppDomain.CurrentDomain.GetAssemblies() + where !assembly.IsDynamic + let reference = MetadataReference.CreateFromFile(assembly.Location) + select reference; + + var compilation = CSharpCompilation.Create( + "original.Sample", + new[] { syntaxTree }, + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + + var compilationDiagnostics = compilation.GetDiagnostics(); + + Assert.IsTrue(compilationDiagnostics.All(x => x.Severity != DiagnosticSeverity.Error), $"Expected no compilation errors before source generation. Got: \n{string.Join("\n", compilationDiagnostics.Where(x => x.Severity == DiagnosticSeverity.Error).Select(x => $"[{x.Id}: {x.GetMessage()}]"))}"); + + IIncrementalGenerator generator = new TGenerator(); + + GeneratorDriver driver = + CSharpGeneratorDriver + .Create(generator) + .WithUpdatedParseOptions((CSharpParseOptions)syntaxTree.Options); + + _ = driver.RunGeneratorsAndUpdateCompilation(compilation, out Compilation outputCompilation, out ImmutableArray diagnostics); + + HashSet resultingIds = diagnostics.Select(diagnostic => diagnostic.Id).ToHashSet(); + var generatedCompilationDiaghostics = outputCompilation.GetDiagnostics(); + + Assert.IsTrue(resultingIds.SetEquals(diagnosticsIds), $"Expected one of [{string.Join(", ", diagnosticsIds)}] diagnostic Ids. Got [{string.Join(", ", resultingIds)}]"); + Assert.IsTrue(generatedCompilationDiaghostics.All(x => x.Severity != DiagnosticSeverity.Error), $"Expected no generated compilation errors. Got: \n{string.Join("\n", generatedCompilationDiaghostics.Where(x => x.Severity == DiagnosticSeverity.Error).Select(x => $"[{x.Id}: {x.GetMessage()}]"))}"); + + GC.KeepAlive(attributeType); + } +} diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj new file mode 100644 index 000000000..9b3c8d237 --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj @@ -0,0 +1,14 @@ + + + + netstandard2.0 + enable + nullable + 10.0 + + + + + + + diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Diagnostics/DiagnosticDescriptors.cs b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Diagnostics/DiagnosticDescriptors.cs new file mode 100644 index 000000000..c9a304039 --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Diagnostics/DiagnosticDescriptors.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis; + +namespace CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Diagnostics; + +/// +/// A container for all instances for errors reported by analyzers in this project. +/// +public static class DiagnosticDescriptors +{ + /// + /// Gets a indicating that a test method decorated with asks for a control instance with a non-parameterless constructor. + /// + /// Format: "Cannot generate test with type {0} as it has a constructor with parameters.". + /// + /// + public static readonly DiagnosticDescriptor TestControlHasConstructorWithParameters = new( + id: "LUITM0001", + title: $"Provided control must not have a constructor with parameters.", + messageFormat: $"Cannot generate test with control {{0}} as it has a constructor with parameters.", + category: typeof(LabsUITestMethodGenerator).FullName, + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: $"Cannot generate test method with provided control."); +} diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Extensions/ISymbolExtensions.cs b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Extensions/ISymbolExtensions.cs new file mode 100644 index 000000000..a95702b75 --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Extensions/ISymbolExtensions.cs @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Extensions; + +/// +/// Extension methods for the type. +/// +/// +/// Borrowed from ISymbolExtensions in the dotnet Toolkit's CommunityToolkit.Mvvm.SourceGenerators project. +/// +internal static class ISymbolExtensions +{ + /// + /// Gets the fully qualified name for a given symbol. + /// + /// The input instance. + /// The fully qualified name for . + public static string GetFullyQualifiedName(this ISymbol symbol) + { + return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + } + + /// + /// Gets the fully qualified name for a given symbol, including nullability annotations + /// + /// The input instance. + /// The fully qualified name for . + public static string GetFullyQualifiedNameWithNullabilityAnnotations(this ISymbol symbol) + { + return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.AddMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier)); + } + + /// + /// Checks whether or not a given type symbol has a specified full name. + /// + /// The input instance to check. + /// The full name to check. + /// Whether has a full name equals to . + public static bool HasFullyQualifiedName(this ISymbol symbol, string name) + { + return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == name; + } + + /// + /// Checks whether or not a given symbol has an attribute with the specified full name. + /// + /// The input instance to check. + /// The attribute name to look for. + /// Whether or not has an attribute with the specified name. + public static bool HasAttributeWithFullyQualifiedName(this ISymbol symbol, string name) + { + ImmutableArray attributes = symbol.GetAttributes(); + + foreach (AttributeData attribute in attributes) + { + if (attribute.AttributeClass?.HasFullyQualifiedName(name) == true) + { + return true; + } + } + + return false; + } + + /// + /// Calculates the effective accessibility for a given symbol. + /// + /// The instance to check. + /// The effective accessibility for . + public static Accessibility GetEffectiveAccessibility(this ISymbol symbol) + { + // Start by assuming it's visible + Accessibility visibility = Accessibility.Public; + + // Handle special cases + switch (symbol.Kind) + { + case SymbolKind.Alias: return Accessibility.Private; + case SymbolKind.Parameter: return GetEffectiveAccessibility(symbol.ContainingSymbol); + case SymbolKind.TypeParameter: return Accessibility.Private; + } + + // Traverse the symbol hierarchy to determine the effective accessibility + while (symbol is not null && symbol.Kind != SymbolKind.Namespace) + { + switch (symbol.DeclaredAccessibility) + { + case Accessibility.NotApplicable: + case Accessibility.Private: + return Accessibility.Private; + case Accessibility.Internal: + case Accessibility.ProtectedAndInternal: + visibility = Accessibility.Internal; + break; + } + + symbol = symbol.ContainingSymbol; + } + + return visibility; + } + + /// + /// Checks whether or not a given symbol can be accessed from a specified assembly. + /// + /// The input instance to check. + /// The assembly to check the accessibility of for. + /// Whether can access . + public static bool CanBeAccessedFrom(this ISymbol symbol, IAssemblySymbol assembly) + { + Accessibility accessibility = symbol.GetEffectiveAccessibility(); + + return + accessibility == Accessibility.Public || + accessibility == Accessibility.Internal && symbol.ContainingAssembly.GivesAccessTo(assembly); + } +} diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Extensions/ITypeSymbolExtensions.cs b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Extensions/ITypeSymbolExtensions.cs new file mode 100644 index 000000000..7d4f813c4 --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/Extensions/ITypeSymbolExtensions.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Extensions; + +/// +/// Extension methods for the type. +/// +/// Borrowed from ITypeSymbolExtensions in the dotnet Toolkit's CommunityToolkit.Mvvm.SourceGenerators project. +/// +internal static class ITypeSymbolExtensions +{ + /// + /// Checks whether or not a given has or inherits from a specified type. + /// + /// The target instance to check. + /// The full name of the type to check for inheritance. + /// Whether or not is or inherits from . + public static bool HasOrInheritsFromFullyQualifiedName(this ITypeSymbol typeSymbol, string name) + { + for (var currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType) + { + if (currentType.HasFullyQualifiedName(name)) + { + return true; + } + } + + return false; + } + + /// + /// Checks whether or not a given inherits from a specified type. + /// + /// The target instance to check. + /// The full name of the type to check for inheritance. + /// Whether or not inherits from . + public static bool InheritsFromFullyQualifiedName(this ITypeSymbol typeSymbol, string name) + { + var baseType = typeSymbol.BaseType; + + while (baseType != null) + { + if (baseType.HasFullyQualifiedName(name)) + { + return true; + } + + baseType = baseType.BaseType; + } + + return false; + } + + /// + /// Checks whether or not a given implements an interface with a specified name. + /// + /// The target instance to check. + /// The full name of the type to check for interface implementation. + /// Whether or not has an interface with the specified name. + public static bool HasInterfaceWithFullyQualifiedName(this ITypeSymbol typeSymbol, string name) + { + foreach (var interfaceType in typeSymbol.AllInterfaces) + { + if (interfaceType.HasFullyQualifiedName(name)) + { + return true; + } + } + + return false; + } + + /// + /// Checks whether or not a given has or inherits a specified attribute. + /// + /// The target instance to check. + /// The predicate used to match available attributes. + /// Whether or not has an attribute matching . + public static bool HasOrInheritsAttribute(this ITypeSymbol typeSymbol, Func predicate) + { + for (var currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType) + { + if (currentType.GetAttributes().Any(predicate)) + { + return true; + } + } + + return false; + } + + /// + /// Checks whether or not a given has or inherits a specified attribute. + /// + /// The target instance to check. + /// The name of the attribute to look for. + /// Whether or not has an attribute with the specified type name. + public static bool HasOrInheritsAttributeWithFullyQualifiedName(this ITypeSymbol typeSymbol, string name) + { + for (var currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType) + { + if (currentType.HasAttributeWithFullyQualifiedName(name)) + { + return true; + } + } + + return false; + } + + /// + /// Checks whether or not a given inherits a specified attribute. + /// If the type has no base type, this method will automatically handle that and return . + /// + /// The target instance to check. + /// The name of the attribute to look for. + /// Whether or not has an attribute with the specified type name. + public static bool InheritsAttributeWithFullyQualifiedName(this ITypeSymbol typeSymbol, string name) + { + if (typeSymbol.BaseType is INamedTypeSymbol baseTypeSymbol) + { + return baseTypeSymbol.HasOrInheritsAttributeWithFullyQualifiedName(name); + } + + return false; + } +} diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/LabsUITestMethodAttribute.cs b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/LabsUITestMethodAttribute.cs new file mode 100644 index 000000000..b5f05b575 --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/LabsUITestMethodAttribute.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + +/// +/// Generates a test method that auto-dispatches method contents to the UI thread, +/// and provides an instance of a control as a parameter if present in the method signature. +/// +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +public sealed class LabsUITestMethodAttribute : Attribute +{ +} diff --git a/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/LabsUITestMethodGenerator.cs b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/LabsUITestMethodGenerator.cs new file mode 100644 index 000000000..e60a249fc --- /dev/null +++ b/common/CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod/LabsUITestMethodGenerator.cs @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Diagnostics; +using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.Linq; + +namespace CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; + +/// +/// Generates code that provides access to XAML elements with x:Name from code-behind by wrapping an instance of a control, without the need to use x:FieldProvider="public" directly in markup. +/// +[Generator] +public class LabsUITestMethodGenerator : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + // Get all method declarations with at least one attribute + var methodSymbols = context.SyntaxProvider + .CreateSyntaxProvider( + static (node, _) => node is MethodDeclarationSyntax { Parent: ClassDeclarationSyntax, AttributeLists.Count: > 0 }, + static (context, token) => context.SemanticModel.GetDeclaredSymbol((MethodDeclarationSyntax)context.Node, cancellationToken: token)) + .Where(x => x is not null) + .Select((x, _) => x!); + + // Filter the methods using [LabsUITestMethod] + var methodAndPageTypeSymbols = methodSymbols + .Select(static (item, _) => + ( + Symbol: item, + Attribute: item.GetAttributes().FirstOrDefault(a => a.AttributeClass?.HasFullyQualifiedName("global::CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.LabsUITestMethodAttribute") ?? false) + )) + + .Where(static item => item.Attribute is not null && item.Symbol is IMethodSymbol) + .Select(static (x, _) => (IMethodSymbol)x.Symbol) + + .Select(static (x, _) => (MethodSymbol: x, ControlTypeSymbol: GetControlTypeSymbolFromMethodParameters(x))) + + .Where(static x => x.ControlTypeSymbol is not null) + .Select(static (x, _) => (x.MethodSymbol, ControlTypeSymbol: x.ControlTypeSymbol!)); + + // Generate source + context.RegisterSourceOutput(methodAndPageTypeSymbols, (x, y) => GenerateTestMethod(x, y.MethodSymbol, y.ControlTypeSymbol)); + } + + private static void GenerateTestMethod(SourceProductionContext context, IMethodSymbol methodSymbol, INamedTypeSymbol? controlTypeSymbol) + { + if (controlTypeSymbol is not null && controlTypeSymbol.Constructors.Any(x => x.DeclaredAccessibility == Accessibility.Public && !x.Parameters.IsEmpty)) + { + context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.TestControlHasConstructorWithParameters, methodSymbol.Locations.FirstOrDefault(), controlTypeSymbol.Name)); + return; + } + + var isAsync = methodSymbol.ReturnType.HasFullyQualifiedName("global::System.Threading.Tasks.Task") || + methodSymbol.ReturnType.InheritsFromFullyQualifiedName("global::System.Threading.Tasks.Task"); + + var source = $@"using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace {methodSymbol.ContainingType.ContainingNamespace} +{{ + partial class {methodSymbol.ContainingType.Name} + {{ + [TestMethod] + public Task {methodSymbol.Name}_Test() + {{ + return EnqueueAsync(async () => {{ + {(controlTypeSymbol is not null ? @$" + // Create content + var testControl = new {controlTypeSymbol.GetFullyQualifiedName()}(); + + // Load content + await LoadTestContentAsync(testControl);" : string.Empty)} + + // Run test + {(isAsync ? "await " : string.Empty)}{methodSymbol.Name}({(controlTypeSymbol is not null ? "testControl" : string.Empty)}); + + {(controlTypeSymbol is not null ? + @"// Unload content + await UnloadTestContentAsync(testControl);" : string.Empty)} + }}); + }} + }} +}} +"; + + context.AddSource($"{methodSymbol.Name}.g", source); + } + + private static bool ControlTypeInheritsFrameworkElement(ITypeSymbol controlType) + { + return controlType.HasOrInheritsFromFullyQualifiedName("global::Windows.UI.Xaml.FrameworkElement") || + controlType.HasOrInheritsFromFullyQualifiedName("global::Microsoft.UI.Xaml.FrameworkElement"); + } + + private static INamedTypeSymbol? GetControlTypeSymbolFromMethodParameters(IMethodSymbol methodSymbol) + { + return methodSymbol.Parameters.FirstOrDefault(x => ControlTypeInheritsFrameworkElement(x.Type))?.Type as INamedTypeSymbol; + } +} + diff --git a/common/CommunityToolkit.Labs.UnitTests.Shared/App.xaml.cs b/common/CommunityToolkit.Labs.UnitTests.Shared/App.xaml.cs index 3b77613fb..0225f5757 100644 --- a/common/CommunityToolkit.Labs.UnitTests.Shared/App.xaml.cs +++ b/common/CommunityToolkit.Labs.UnitTests.Shared/App.xaml.cs @@ -45,20 +45,8 @@ public sealed partial class App : Application // Holder for test content to abstract Window.Current.Content public static FrameworkElement? ContentRoot { - get - { - var rootFrame = currentWindow.Content as Frame; - return rootFrame?.Content as FrameworkElement; - } - - set - { - var rootFrame = currentWindow.Content as Frame; - if (rootFrame != null) - { - rootFrame.Content = value; - } - } + get => currentWindow.Content as FrameworkElement; + set => currentWindow.Content = value; } // Abstract CoreApplication.MainView.DispatcherQueue diff --git a/common/CommunityToolkit.Labs.UnitTests.Shared/CommunityToolkit.Labs.UnitTests.Shared.projitems b/common/CommunityToolkit.Labs.UnitTests.Shared/CommunityToolkit.Labs.UnitTests.Shared.projitems index f14f94ed2..8a363fae1 100644 --- a/common/CommunityToolkit.Labs.UnitTests.Shared/CommunityToolkit.Labs.UnitTests.Shared.projitems +++ b/common/CommunityToolkit.Labs.UnitTests.Shared/CommunityToolkit.Labs.UnitTests.Shared.projitems @@ -19,7 +19,6 @@ App.xaml - \ No newline at end of file diff --git a/common/CommunityToolkit.Labs.UnitTests.Shared/TestPageAttribute.cs b/common/CommunityToolkit.Labs.UnitTests.Shared/TestPageAttribute.cs deleted file mode 100644 index 1c499a074..000000000 --- a/common/CommunityToolkit.Labs.UnitTests.Shared/TestPageAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace CommunityToolkit.Labs.UnitTests; - -/// -/// Attribute to add to a implementation in order to load a XAML based page to use within that test. Class with containing method needs to inherit from for functionality to work. Requires to be set to function. -/// -[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] -public sealed class TestPageAttribute : Attribute -{ - public TestPageAttribute(Type pageType) - { - if (pageType == null) - { - throw new ArgumentException($"'{nameof(pageType)}' cannot be null", nameof(pageType)); - } - - PageType = pageType; - } - - public Type PageType { get; private set; } -} diff --git a/common/CommunityToolkit.Labs.UnitTests.Shared/VisualUITestBase.cs b/common/CommunityToolkit.Labs.UnitTests.Shared/VisualUITestBase.cs index ce59a7675..300c41b50 100644 --- a/common/CommunityToolkit.Labs.UnitTests.Shared/VisualUITestBase.cs +++ b/common/CommunityToolkit.Labs.UnitTests.Shared/VisualUITestBase.cs @@ -11,33 +11,14 @@ namespace CommunityToolkit.Labs.UnitTests; /// public class VisualUITestBase { - public TestContext? TestContext { get; set; } + // Used by source generators to dispatch to the UI thread + // Methods must be declared or interfaced for compatibility with the source generator's unit tests. - public FrameworkElement? TestPage { get; private set; } + protected Task EnqueueAsync(Func> function) => App.DispatcherQueue.EnqueueAsync(function); - [TestInitialize] - public async Task TestInitialize() - { - if (TestContext != null) - { - await App.DispatcherQueue.EnqueueAsync(async () => - { - TestPage = GetPageForTest(TestContext); - - if (TestPage != null) - { - Task result = SetTestContentAsync(TestPage); - - await result; - - if (!result.IsCompletedSuccessfully) - { - throw new Exception($"Failed to load page for {TestContext.TestName} with Exception: {result.Exception?.Message}", result.Exception); - } - } - }); - } - } + protected Task EnqueueAsync(Func function) => App.DispatcherQueue.EnqueueAsync(function); + + protected Task EnqueueAsync(Action function) => App.DispatcherQueue.EnqueueAsync(function); /// /// Sets the content of the test app to a simple to load into the visual tree. @@ -45,111 +26,62 @@ await App.DispatcherQueue.EnqueueAsync(async () => /// /// Content to set in test app. /// When UI is loaded. - protected Task SetTestContentAsync(FrameworkElement content) - { - return App.DispatcherQueue.EnqueueAsync(() => - { - var taskCompletionSource = new TaskCompletionSource(); - - async void Callback(object sender, RoutedEventArgs args) - { - content.Loaded -= Callback; - - // Wait for first Render pass - await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { }); + protected async Task LoadTestContentAsync(FrameworkElement content) + { + var taskCompletionSource = new TaskCompletionSource(); - taskCompletionSource.SetResult(true); - } + content.Loaded += OnLoaded; + App.ContentRoot = content; - // Going to wait for our original content to unload - content.Loaded += Callback; - - // Trigger that now - try - { - App.ContentRoot = content; - } - catch (Exception e) - { - taskCompletionSource.SetException(e); - } - - return taskCompletionSource.Task; - }); - } - - [TestCleanup] - public async Task Cleanup() - { - var taskCompletionSource = new TaskCompletionSource(); + await taskCompletionSource.Task; + Assert.IsTrue(content.IsLoaded); - await App.DispatcherQueue.EnqueueAsync(() => + async void OnLoaded(object sender, RoutedEventArgs args) { - // If we didn't set our content we don't have to do anything but complete here. - if (App.ContentRoot is null) - { - taskCompletionSource.SetResult(true); - return; - } - - // Going to wait for our original content to unload - App.ContentRoot.Unloaded += (_, _) => taskCompletionSource.SetResult(true); + content.Loaded -= OnLoaded; - TestPage = null; + // Wait for first Render pass + await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { }); - // Trigger that now - App.ContentRoot = null; - }); - - await taskCompletionSource.Task; + taskCompletionSource.SetResult(null); + } } - private static FrameworkElement? GetPageForTest(TestContext testContext) + public async Task UnloadTestContentAsync(FrameworkElement element) { - var testName = testContext.TestName; - var theClassName = testContext.FullyQualifiedTestClassName; - - var testClassString = $"test class \"{theClassName}\""; - if (Type.GetType(theClassName) is not Type type) - { - throw new Exception($"Could not find {testClassString}."); - } - - Log.Comment($"Found {testClassString}."); + var taskCompletionSource = new TaskCompletionSource(); - var testMethodString = $"test method \"{testName}\" in {testClassString}"; - if (type.GetMethod(testName) is not MethodInfo method) - { - throw new Exception($"Could not find {testMethodString}."); - } + element.Unloaded += OnUnloaded; - Log.Comment($"Found {testMethodString}."); + App.ContentRoot = null; - var testpageAttributeString = $"\"{typeof(TestPageAttribute)}\" on {testMethodString}"; - if (method.GetCustomAttribute(typeof(TestPageAttribute), true) is not TestPageAttribute attribute) - { - // If we don't have an attribute, we'll return null here to indicate such. - // Otherwise, we'll be throwing an exception on failure anyway below. - return null; - } + await taskCompletionSource.Task; + Assert.IsFalse(element.IsLoaded); - if (attribute.PageType is null) + void OnUnloaded(object sender, RoutedEventArgs args) { - throw new Exception($"{testpageAttributeString} requires `PageType` to be set."); + element.Unloaded -= OnUnloaded; + taskCompletionSource.SetResult(null); } + } - var obj = Activator.CreateInstance(attribute.PageType); + [TestInitialize] + public virtual Task TestSetup() => EnqueueAsync(async () => + { + // Make sure every test starts with a clean slate, even if it doesn't use LoadTestContentAsync. + if (App.ContentRoot is FrameworkElement element) + await UnloadTestContentAsync(element); - if (obj is null) - { - throw new Exception($"Could not instantiate page of type {attribute.PageType.FullName} for {testpageAttributeString}."); - } + Assert.IsNull(App.ContentRoot); + }); - if (obj is FrameworkElement element) - { - return element; - } + [TestCleanup] + public virtual Task TestCleanup() => EnqueueAsync(async () => + { + // Make sure every test ends with a clean slate, even if it doesn't use LoadTestContentAsync. + if (App.ContentRoot is FrameworkElement element) + await UnloadTestContentAsync(element); - throw new Exception($"{attribute.PageType.FullName} is required to inherit from `FrameworkElement` for the {testpageAttributeString}."); - } + Assert.IsNull(App.ContentRoot); + }); } diff --git a/common/Toolkit.Labs.All.sln.template b/common/Toolkit.Labs.All.sln.template index 740be9f09..57452fa82 100644 --- a/common/Toolkit.Labs.All.sln.template +++ b/common/Toolkit.Labs.All.sln.template @@ -58,6 +58,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Labs.UnitT EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Experiments", "Experiments", "{DD69BA61-C86D-4138-AE6F-76E2C8445C9A}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod", "common\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj", "{CA16C45E-DFB1-4641-A28D-EC52B6FB370A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests", "common\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.Tests.csproj", "{6961F49B-705D-47E0-81C3-D8CF7741C3E4}" +EndProject [TemplatedProjectDefinitions] Global GlobalSection(SharedMSBuildProjectFiles) = preSolution @@ -1000,6 +1004,118 @@ Global {53892F07-FE54-4E36-81D8-105427D097E5}.Release|x86.ActiveCfg = Release|x86 {53892F07-FE54-4E36-81D8-105427D097E5}.Release|x86.Build.0 = Release|x86 {53892F07-FE54-4E36-81D8-105427D097E5}.Release|x86.Deploy.0 = Release|x86 + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|ARM.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|ARM64.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|iPhone.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|x64.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|x64.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|x86.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.AppStore|x86.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|ARM.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|ARM64.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|iPhone.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|x64.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Debug|x86.Build.0 = Debug|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|Any CPU.Build.0 = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|ARM.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|ARM.Build.0 = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|ARM64.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|ARM64.Build.0 = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|iPhone.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|iPhone.Build.0 = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|x64.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|x64.Build.0 = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|x86.ActiveCfg = Release|Any CPU + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A}.Release|x86.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|ARM.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|ARM64.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|iPhone.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|x64.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|x64.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|x86.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.AppStore|x86.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|ARM.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|ARM64.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|iPhone.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|x64.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|x64.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|x86.ActiveCfg = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Debug|x86.Build.0 = Debug|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|Any CPU.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|ARM.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|ARM.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|ARM64.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|ARM64.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|iPhone.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|iPhone.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|x64.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|x64.Build.0 = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|x86.ActiveCfg = Release|Any CPU + {6961F49B-705D-47E0-81C3-D8CF7741C3E4}.Release|x86.Build.0 = Release|Any CPU [TemplatedProjectConfigurations] EndGlobalSection GlobalSection(SolutionProperties) = preSolution @@ -1023,6 +1139,8 @@ Global {FD78002E-C4E6-4BF8-9EC3-C06250DFEF34} = {FF878CF0-59B1-4B8C-A7DB-1E2A7B47575A} {53892F07-FE54-4E36-81D8-105427D097E5} = {FF878CF0-59B1-4B8C-A7DB-1E2A7B47575A} {DD69BA61-C86D-4138-AE6F-76E2C8445C9A} = {FF878CF0-59B1-4B8C-A7DB-1E2A7B47575A} + {CA16C45E-DFB1-4641-A28D-EC52B6FB370A} = {09003B35-7A35-4BD1-9A26-5CFD02AB88DD} + {6961F49B-705D-47E0-81C3-D8CF7741C3E4} = {09003B35-7A35-4BD1-9A26-5CFD02AB88DD} [TemplatedProjectFolderConfig] EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/labs/CanvasLayout/CanvasLayout.sln b/labs/CanvasLayout/CanvasLayout.sln index 8b9a9c8b9..73ecd111d 100644 --- a/labs/CanvasLayout/CanvasLayout.sln +++ b/labs/CanvasLayout/CanvasLayout.sln @@ -29,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CanvasLayout.UnitTests.Uwp" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Labs Dependencies", "Labs Dependencies", "{EC5804D7-C94B-4CF8-8344-132F2A58F88E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod", "..\..\common\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj", "{563D0F3A-84BF-4286-8652-84230D0468D9}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution tests\CanvasLayout.Tests\CanvasLayout.Tests.projitems*{2c7a065b-9349-4071-af95-e88f320a09a9}*SharedItemsImports = 13 @@ -269,6 +271,26 @@ Global {F17EE40D-CEE8-402F-AA43-45A7F87ACBF3}.Release|x86.ActiveCfg = Release|x86 {F17EE40D-CEE8-402F-AA43-45A7F87ACBF3}.Release|x86.Build.0 = Release|x86 {F17EE40D-CEE8-402F-AA43-45A7F87ACBF3}.Release|x86.Deploy.0 = Release|x86 + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|ARM.ActiveCfg = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|ARM.Build.0 = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|ARM64.Build.0 = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|x64.ActiveCfg = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|x64.Build.0 = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|x86.ActiveCfg = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Debug|x86.Build.0 = Debug|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|Any CPU.Build.0 = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|ARM.ActiveCfg = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|ARM.Build.0 = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|ARM64.ActiveCfg = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|ARM64.Build.0 = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|x64.ActiveCfg = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|x64.Build.0 = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|x86.ActiveCfg = Release|Any CPU + {563D0F3A-84BF-4286-8652-84230D0468D9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -281,6 +303,7 @@ Global {B3090946-9399-43C6-AF7C-2E21F5C93935} = {EC5804D7-C94B-4CF8-8344-132F2A58F88E} {DD3E4652-114A-4614-8904-1DBCE62589CC} = {69AFC3EC-DC11-4031-8624-0E9F942D19C3} {F17EE40D-CEE8-402F-AA43-45A7F87ACBF3} = {69AFC3EC-DC11-4031-8624-0E9F942D19C3} + {563D0F3A-84BF-4286-8652-84230D0468D9} = {EC5804D7-C94B-4CF8-8344-132F2A58F88E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6D11723C-7575-40DF-9BC9-300A09554B5D} diff --git a/labs/SizerBase/SizerBase.sln b/labs/SizerBase/SizerBase.sln index 3fa65bbe9..7f36fa8a8 100644 --- a/labs/SizerBase/SizerBase.sln +++ b/labs/SizerBase/SizerBase.sln @@ -29,12 +29,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SizerBase.UnitTests.Uwp", " EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Labs Dependencies", "Labs Dependencies", "{F3172F4D-9A5B-4B0E-8461-EAC2BC6230A5}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod", "..\..\common\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj", "{7B345661-551E-433A-B26A-0168788D1B3B}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - tests\SizerBase.Tests\SizerBase.Tests.projitems*{CC1804EF-1663-464A-AC8C-C38836CB70AF}*SharedItemsImports = 13 - ..\..\common\CommunityToolkit.Labs.Shared\CommunityToolkit.Labs.Shared.projitems*{1F1E15B8-C732-411C-9273-F48702E8E4E4}*SharedItemsImports = 4 - tests\SizerBase.Tests\SizerBase.Tests.projitems*{03580331-0918-4A52-9A9E-C50061A226CF}*SharedItemsImports = 4 - tests\SizerBase.Tests\SizerBase.Tests.projitems*{B914E653-2225-442E-9250-D8EF639777C3}*SharedItemsImports = 5 + tests\SizerBase.Tests\SizerBase.Tests.projitems*{03580331-0918-4a52-9a9e-c50061a226cf}*SharedItemsImports = 4 + ..\..\common\CommunityToolkit.Labs.Shared\CommunityToolkit.Labs.Shared.projitems*{1f1e15b8-c732-411c-9273-f48702e8e4e4}*SharedItemsImports = 4 + tests\SizerBase.Tests\SizerBase.Tests.projitems*{b914e653-2225-442e-9250-d8ef639777c3}*SharedItemsImports = 5 + tests\SizerBase.Tests\SizerBase.Tests.projitems*{cc1804ef-1663-464a-ac8c-c38836cb70af}*SharedItemsImports = 13 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -169,6 +171,46 @@ Global {70DF1194-D158-473E-B350-F630231FB328}.Release|x86.ActiveCfg = Release|x86 {70DF1194-D158-473E-B350-F630231FB328}.Release|x86.Build.0 = Release|x86 {70DF1194-D158-473E-B350-F630231FB328}.Release|x86.Deploy.0 = Release|x86 + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.Build.0 = Release|Any CPU {B914E653-2225-442E-9250-D8EF639777C3}.Debug|Any CPU.ActiveCfg = Debug|x64 {B914E653-2225-442E-9250-D8EF639777C3}.Debug|Any CPU.Build.0 = Debug|x64 {B914E653-2225-442E-9250-D8EF639777C3}.Debug|Any CPU.Deploy.0 = Debug|x64 @@ -229,46 +271,26 @@ Global {03580331-0918-4A52-9A9E-C50061A226CF}.Release|x86.ActiveCfg = Release|x86 {03580331-0918-4A52-9A9E-C50061A226CF}.Release|x86.Build.0 = Release|x86 {03580331-0918-4A52-9A9E-C50061A226CF}.Release|x86.Deploy.0 = Release|x86 - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.Build.0 = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|ARM.Build.0 = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|ARM64.Build.0 = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|x64.ActiveCfg = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|x64.Build.0 = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Debug|x86.Build.0 = Debug|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|Any CPU.Build.0 = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|ARM.ActiveCfg = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|ARM.Build.0 = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|ARM64.ActiveCfg = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|ARM64.Build.0 = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|x64.ActiveCfg = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|x64.Build.0 = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|x86.ActiveCfg = Release|Any CPU + {7B345661-551E-433A-B26A-0168788D1B3B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -277,10 +299,11 @@ Global {1F1E15B8-C732-411C-9273-F48702E8E4E4} = {EF78C64C-AEA9-4A35-AF14-40C392925F47} {50B1FC51-ECC0-480D-80C2-4957622BA2F6} = {EF78C64C-AEA9-4A35-AF14-40C392925F47} {70DF1194-D158-473E-B350-F630231FB328} = {EF78C64C-AEA9-4A35-AF14-40C392925F47} - {B914E653-2225-442E-9250-D8EF639777C3} = {40D1D98D-ED3A-473F-990F-3473948F5E3D} - {03580331-0918-4A52-9A9E-C50061A226CF} = {40D1D98D-ED3A-473F-990F-3473948F5E3D} {66E6DA8A-FEFC-4221-A476-4314A4D692F6} = {F3172F4D-9A5B-4B0E-8461-EAC2BC6230A5} {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91} = {F3172F4D-9A5B-4B0E-8461-EAC2BC6230A5} + {B914E653-2225-442E-9250-D8EF639777C3} = {40D1D98D-ED3A-473F-990F-3473948F5E3D} + {03580331-0918-4A52-9A9E-C50061A226CF} = {40D1D98D-ED3A-473F-990F-3473948F5E3D} + {7B345661-551E-433A-B26A-0168788D1B3B} = {F3172F4D-9A5B-4B0E-8461-EAC2BC6230A5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {ACDAC286-33A3-40F4-884D-16C359D857AE} diff --git a/labs/SizerBase/tests/SizerBase.Tests/ExampleSizerBaseTestClass.cs b/labs/SizerBase/tests/SizerBase.Tests/ExampleSizerBaseTestClass.cs index 8ef03c3e9..14318696e 100644 --- a/labs/SizerBase/tests/SizerBase.Tests/ExampleSizerBaseTestClass.cs +++ b/labs/SizerBase/tests/SizerBase.Tests/ExampleSizerBaseTestClass.cs @@ -5,11 +5,12 @@ using CommunityToolkit.Labs.UnitTests; using CommunityToolkit.Labs.WinUI; using CommunityToolkit.Labs.WinUI.Automation.Peers; +using CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod; namespace SizerBase.Tests; [TestClass] -public class ExampleSizerBaseTestClass : VisualUITestBase +public partial class ExampleSizerBaseTestClass : VisualUITestBase { [TestMethod] public void Just_an_example_test() @@ -20,7 +21,7 @@ public void Just_an_example_test() [TestMethod] public async Task ShouldConfigureGridSplitterAutomationPeer() { - await App.DispatcherQueue.EnqueueAsync(() => + await EnqueueAsync(() => { const string automationName = "MyCustomAutomationName"; const string name = "Sizer"; @@ -38,37 +39,29 @@ await App.DispatcherQueue.EnqueueAsync(() => }); } - [TestMethod] - [TestPage(typeof(PropertySizerTestInitialBinding))] - public async Task PropertySizer_TestInitialBinding() + [LabsUITestMethod] + public void PropertySizer_TestInitialBinding(PropertySizerTestInitialBinding testControl) { - await App.DispatcherQueue.EnqueueAsync(() => { - // TestPage shouldn't be null here, but we'll do the safer ?. to be sure. - var propertySizer = TestPage?.FindDescendant(); + var propertySizer = testControl.FindDescendant(); - Assert.IsNotNull(propertySizer, "Could not find PropertySizer control."); + Assert.IsNotNull(propertySizer, "Could not find PropertySizer control."); - // Set in XAML Page LINK: PropertySizerTestInitialBinding.xaml#L14 - Assert.AreEqual(300, propertySizer.Binding, "Property Sizer not at expected initial value."); - }); + // Set in XAML Page LINK: PropertySizerTestInitialBinding.xaml#L14 + Assert.AreEqual(300, propertySizer.Binding, "Property Sizer not at expected initial value."); } - [TestMethod] - [TestPage(typeof(PropertySizerTestInitialBinding))] - public async Task PropertySizer_TestChangeBinding() + [LabsUITestMethod] + public void PropertySizer_TestChangeBinding(PropertySizerTestInitialBinding testControl) { - await App.DispatcherQueue.EnqueueAsync(() => { - // TestPage shouldn't be null here, but we'll do the safer ?. to be sure. - var propertySizer = TestPage?.FindDescendant(); - var navigationView = TestPage?.FindDescendant(); + var propertySizer = testControl.FindDescendant(); + var navigationView = testControl.FindDescendant(); - Assert.IsNotNull(propertySizer, "Could not find PropertySizer control."); - Assert.IsNotNull(navigationView, "Could not find NavigationView control."); + Assert.IsNotNull(propertySizer, "Could not find PropertySizer control."); + Assert.IsNotNull(navigationView, "Could not find NavigationView control."); - navigationView.OpenPaneLength = 200; + navigationView.OpenPaneLength = 200; - // Set in XAML Page LINK: PropertySizerTestInitialBinding.xaml#L14 - Assert.AreEqual(200, propertySizer.Binding, "Property Sizer not at expected changed value."); - }); + // Set in XAML Page LINK: PropertySizerTestInitialBinding.xaml#L14 + Assert.AreEqual(200, propertySizer.Binding, "Property Sizer not at expected changed value."); } } diff --git a/template/lab/ProjectTemplate.sln b/template/lab/ProjectTemplate.sln index e0fd54ef4..38d65f553 100644 --- a/template/lab/ProjectTemplate.sln +++ b/template/lab/ProjectTemplate.sln @@ -29,11 +29,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectTemplate.UnitTests.U EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Labs Dependencies", "Labs Dependencies", "{D4DCFA4B-63B3-4D93-8C91-FBEE3B92E5A0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod", "..\..\common\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod\CommunityToolkit.Labs.Core.SourceGenerators.LabsUITestMethod.csproj", "{79F79471-9947-45F5-81FE-4EBE2B8D0B1D}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution tests\ProjectTemplate.Tests\ProjectTemplate.Tests.projitems*{19ac7a6a-b001-45aa-acbe-0536f688db74}*SharedItemsImports = 13 - ..\..\common\CommunityToolkit.Labs.Shared\CommunityToolkit.Labs.Shared.projitems*{e25bf6d0-24d6-459c-a180-1e9405d59f87}*SharedItemsImports = 4 tests\ProjectTemplate.Tests\ProjectTemplate.Tests.projitems*{7134bd2e-0a74-4345-868a-e425fc452a89}*SharedItemsImports = 4 + ..\..\common\CommunityToolkit.Labs.Shared\CommunityToolkit.Labs.Shared.projitems*{e25bf6d0-24d6-459c-a180-1e9405d59f87}*SharedItemsImports = 4 tests\ProjectTemplate.Tests\ProjectTemplate.Tests.projitems*{fe390707-a244-460a-bc1c-5559038a1975}*SharedItemsImports = 5 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -169,6 +171,46 @@ Global {ED318A01-D129-4F06-A9EB-8D911000E243}.Release|x86.ActiveCfg = Release|x86 {ED318A01-D129-4F06-A9EB-8D911000E243}.Release|x86.Build.0 = Release|x86 {ED318A01-D129-4F06-A9EB-8D911000E243}.Release|x86.Deploy.0 = Release|x86 + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.Build.0 = Debug|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.Build.0 = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.ActiveCfg = Release|Any CPU + {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.ActiveCfg = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.Build.0 = Debug|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.Build.0 = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.ActiveCfg = Release|Any CPU + {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.Build.0 = Release|Any CPU {FE390707-A244-460A-BC1C-5559038A1975}.Debug|Any CPU.ActiveCfg = Debug|x64 {FE390707-A244-460A-BC1C-5559038A1975}.Debug|Any CPU.Build.0 = Debug|x64 {FE390707-A244-460A-BC1C-5559038A1975}.Debug|Any CPU.Deploy.0 = Debug|x64 @@ -229,46 +271,26 @@ Global {7134BD2E-0A74-4345-868A-E425FC452A89}.Release|x86.ActiveCfg = Release|x86 {7134BD2E-0A74-4345-868A-E425FC452A89}.Release|x86.Build.0 = Release|x86 {7134BD2E-0A74-4345-868A-E425FC452A89}.Release|x86.Deploy.0 = Release|x86 - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|ARM64.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x64.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.ActiveCfg = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Debug|x86.Build.0 = Debug|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|Any CPU.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|ARM64.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x64.Build.0 = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.ActiveCfg = Release|Any CPU - {66E6DA8A-FEFC-4221-A476-4314A4D692F6}.Release|x86.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|ARM64.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x64.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.ActiveCfg = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Debug|x86.Build.0 = Debug|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|Any CPU.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|ARM64.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x64.Build.0 = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.ActiveCfg = Release|Any CPU - {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91}.Release|x86.Build.0 = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|ARM.Build.0 = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|ARM64.Build.0 = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|x64.ActiveCfg = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|x64.Build.0 = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|x86.ActiveCfg = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Debug|x86.Build.0 = Debug|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|Any CPU.Build.0 = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|ARM.ActiveCfg = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|ARM.Build.0 = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|ARM64.ActiveCfg = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|ARM64.Build.0 = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|x64.ActiveCfg = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|x64.Build.0 = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|x86.ActiveCfg = Release|Any CPU + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -277,10 +299,11 @@ Global {E25BF6D0-24D6-459C-A180-1E9405D59F87} = {ACD20BEE-45EF-4CAB-BA06-40F38A0C98EA} {507C24FC-DD1C-4B91-BB6F-4A4CFB30A252} = {ACD20BEE-45EF-4CAB-BA06-40F38A0C98EA} {ED318A01-D129-4F06-A9EB-8D911000E243} = {ACD20BEE-45EF-4CAB-BA06-40F38A0C98EA} - {FE390707-A244-460A-BC1C-5559038A1975} = {7F03DDE8-FC53-451D-B0A4-E852EC44C0E9} - {7134BD2E-0A74-4345-868A-E425FC452A89} = {7F03DDE8-FC53-451D-B0A4-E852EC44C0E9} {66E6DA8A-FEFC-4221-A476-4314A4D692F6} = {D4DCFA4B-63B3-4D93-8C91-FBEE3B92E5A0} {7A1E5FBF-B51A-4B56-8EA3-6AB56A7E9D91} = {D4DCFA4B-63B3-4D93-8C91-FBEE3B92E5A0} + {FE390707-A244-460A-BC1C-5559038A1975} = {7F03DDE8-FC53-451D-B0A4-E852EC44C0E9} + {7134BD2E-0A74-4345-868A-E425FC452A89} = {7F03DDE8-FC53-451D-B0A4-E852EC44C0E9} + {79F79471-9947-45F5-81FE-4EBE2B8D0B1D} = {D4DCFA4B-63B3-4D93-8C91-FBEE3B92E5A0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A17E5FCF-1282-4567-A5BC-811F2F45DD7E} diff --git a/tests/Labs.Tests.props b/tests/Labs.Tests.props index 078514d0e..034fc48b4 100644 --- a/tests/Labs.Tests.props +++ b/tests/Labs.Tests.props @@ -4,9 +4,13 @@ 2.2.8 + 2.2.8 + +