-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #131 from MADE-Apps/feature/pageobjectgenerator
Implemented basic page object generator
- Loading branch information
Showing
19 changed files
with
673 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,17 @@ | ||
## Fixes # | ||
## Resolves # | ||
<!-- Add the issue ID after the '#' to automatically close the issue once the PR is merged --> | ||
|
||
<!-- Please provide a description below of the changes made and how it has been tested --> | ||
|
||
## PR checklist | ||
|
||
- [ ] Sample tests have been added/updated and pass | ||
- [ ] [Documentation](/docs) has been added/updated for changes | ||
- [ ] Code styling has been met on new source file changes | ||
- [ ] Contains **NO** breaking changes | ||
- [ ] Have Uno Platform samples and Legerity tests been added or updated, run locally, and all pass | ||
- [ ] Have added or updated support for Uno Platform element wrappers been reflected in the Page Object Generator | ||
- [ ] Have code styling rules been run on all new source file changes | ||
- [ ] Have relevant articles in the docs been added or updated for all new source file changes | ||
- [ ] Have major breaking changes been made and are documented | ||
|
||
<!-- If a breaking change has been made, please provide a detailed description below of the impact and the migration path --> | ||
|
||
## Other information | ||
<!-- Please provide any additional information, links, or screenshots below if applicable --> | ||
<!-- Provide any additional information below that may be relevant to the changes made (e.g. app screenshots, documentation links, or existing PR reference) --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<Project> | ||
|
||
<PropertyGroup> | ||
<PublishRepositoryUrl>true</PublishRepositoryUrl> | ||
<EmbedUntrackedSources>true</EmbedUntrackedSources> | ||
<IncludeSymbols>true</IncludeSymbols> | ||
<SymbolPackageFormat>snupkg</SymbolPackageFormat> | ||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||
<Version>1.0.0.0</Version> | ||
<Authors>MADE Apps</Authors> | ||
<Company>MADE Apps</Company> | ||
<Copyright>Copyright (C) MADE Apps. All rights reserved.</Copyright> | ||
<PackageProjectUrl>https://github.com/MADE-Apps/legerity-uno</PackageProjectUrl> | ||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | ||
<PackageIcon>ProjectLogo.png</PackageIcon> | ||
<PackageReleaseNotes>https://github.com/MADE-Apps/legerity-uno/releases</PackageReleaseNotes> | ||
<NeutralLanguage>en</NeutralLanguage> | ||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
<LangVersion>latest</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<None Include="..\..\assets\ProjectLogo.png" Pack="true" PackagePath=""/> | ||
<None Include="..\..\LICENSE" Pack="true" PackagePath=""/> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/> | ||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive"/> | ||
</ItemGroup> | ||
|
||
</Project> |
26 changes: 26 additions & 0 deletions
26
tools/Legerity.Uno.PageObjectGenerator/Features/Generator/Models/GeneratorTemplateData.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
namespace Legerity.Uno.Features.Generator.Models; | ||
|
||
using System.Collections.Generic; | ||
|
||
internal class GeneratorTemplateData | ||
{ | ||
public GeneratorTemplateData(string ns, string page, string baseElementType) | ||
{ | ||
this.Namespace = ns; | ||
this.Page = page; | ||
this.Type = baseElementType; | ||
} | ||
|
||
public string Page { get; set; } | ||
|
||
public string Type { get; set; } | ||
|
||
public string Namespace { get; set; } | ||
|
||
public List<UiElement> Elements { get; set; } = new(); | ||
|
||
public override string ToString() | ||
{ | ||
return $"[Page] {this.Page}"; | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
tools/Legerity.Uno.PageObjectGenerator/Features/Generator/Models/UiElement.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
namespace Legerity.Uno.Features.Generator.Models; | ||
|
||
internal class UiElement | ||
{ | ||
public UiElement(string type, string name, string by, string value) | ||
{ | ||
this.Type = type; | ||
this.Name = name; | ||
this.By = by; | ||
this.Value = value; | ||
} | ||
|
||
public string Type { get; set; } | ||
|
||
public string Name { get; set; } | ||
|
||
public string By { get; set; } | ||
|
||
public string Value { get; set; } | ||
|
||
public override string ToString() | ||
{ | ||
return $"[Type] {this.Type}; [Name] {this.Name}; [By] {this.By}; [Value] {this.Value};"; | ||
} | ||
} |
158 changes: 158 additions & 0 deletions
158
tools/Legerity.Uno.PageObjectGenerator/Features/Generator/XamlPageObjectGenerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
namespace Legerity.Uno.Features.Generator; | ||
|
||
using System.Text; | ||
using System.Xml.Linq; | ||
using Infrastructure.Extensions; | ||
using Infrastructure.IO; | ||
using Legerity.Uno.Features.Generator.Models; | ||
using MADE.Collections.Compare; | ||
using MADE.Data.Validation.Extensions; | ||
using Scriban; | ||
using Serilog; | ||
|
||
internal class XamlPageObjectGenerator | ||
{ | ||
private const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; | ||
|
||
private static readonly GenericEqualityComparer<string> SimpleStringComparer = new(s => s.ToLower()); | ||
|
||
private const string BaseElementType = "RemoteWebElement"; | ||
|
||
private static IEnumerable<string> SupportedUnoPlatformElements => new List<string> | ||
{ | ||
"AppBarButton", | ||
"AppBarToggleButton", | ||
"Button", | ||
"CheckBox", | ||
"ComboBox", | ||
"CommandBar", | ||
"DatePicker", | ||
"HyperlinkButton", | ||
"TextBlock", | ||
"TextBox", | ||
"TimePicker" | ||
}; | ||
|
||
internal async Task GenerateAsync(string ns, string inputPath, string outputPath) | ||
{ | ||
IEnumerable<string>? filePaths = GetXamlFilePaths(inputPath)?.ToList(); | ||
|
||
if (filePaths == null || !filePaths.Any()) | ||
{ | ||
Log.Warning("No XAML files found in {InputPath}", inputPath); | ||
return; | ||
} | ||
|
||
foreach (string filePath in filePaths) | ||
{ | ||
Log.Information($"Processing {filePath}"); | ||
|
||
await using FileStream fileStream = File.Open(filePath, FileMode.Open); | ||
var xaml = XDocument.Load(fileStream); | ||
|
||
if (xaml.Root != null && xaml.Root.Name.ToString().Contains("Page")) | ||
{ | ||
var templateData = | ||
new GeneratorTemplateData(ns, Path.GetFileNameWithoutExtension(filePath), BaseElementType); | ||
|
||
Log.Information($"Generating template for {templateData}"); | ||
|
||
IEnumerable<XElement> elements = this.FlattenElements(xaml.Root.Elements()); | ||
foreach (XElement element in elements) | ||
{ | ||
string? automationId = element.Attribute("AutomationProperties.AutomationId")?.Value; | ||
string? uid = element.Attribute(XName.Get("Uid", XamlNamespace))?.Value; | ||
string? name = element.Attribute(XName.Get("Name", XamlNamespace))?.Value; | ||
|
||
string? byLocatorType = GetByLocatorType(uid, automationId, name); | ||
|
||
if (byLocatorType == null || byLocatorType.IsNullOrWhiteSpace()) | ||
{ | ||
continue; | ||
} | ||
|
||
string? wrapperAutomationId = uid ?? automationId; | ||
string? byQueryValue = wrapperAutomationId ?? name; | ||
|
||
if (byQueryValue == null || byQueryValue.IsNullOrWhiteSpace()) | ||
{ | ||
continue; | ||
} | ||
|
||
var uiElement = new UiElement(GetElementWrapperType(element.Name.LocalName), | ||
byQueryValue.Capitalize(), | ||
byLocatorType, | ||
byQueryValue); | ||
|
||
Log.Information($"Element found on page - {uiElement}"); | ||
|
||
templateData.Elements.Add(uiElement); | ||
} | ||
|
||
await GeneratePageObjectClassFileAsync(templateData, outputPath); | ||
} | ||
else | ||
{ | ||
Log.Warning($"Skipping {filePath} as a page was not detected"); | ||
} | ||
} | ||
} | ||
|
||
private static async Task GeneratePageObjectClassFileAsync( | ||
GeneratorTemplateData templateData, | ||
string outputFolder) | ||
{ | ||
var pageObjectTemplate = Template.Parse(await EmbeddedResourceLoader.ReadAsync("Legerity.Uno.Templates.UnoPageObject.template")); | ||
|
||
string outputFile = $"{templateData.Page}.cs"; | ||
|
||
Log.Information($"Generating {outputFile} page object file"); | ||
string result = await pageObjectTemplate.RenderAsync(templateData); | ||
|
||
FileStream output = File.Create(Path.Combine(outputFolder, outputFile)); | ||
var outputWriter = new StreamWriter(output, Encoding.UTF8); | ||
|
||
await using (outputWriter) | ||
{ | ||
await outputWriter.WriteAsync(result); | ||
} | ||
} | ||
|
||
private static string? GetByLocatorType(string? uid, string? automationId, string? name) | ||
{ | ||
if ((uid != null && !uid.IsNullOrWhiteSpace()) || (automationId != null && !automationId.IsNullOrWhiteSpace())) | ||
{ | ||
return "AutomationId"; | ||
} | ||
|
||
return name != null && !name.IsNullOrWhiteSpace() ? "Name" : null; | ||
} | ||
|
||
private static IEnumerable<string>? GetXamlFilePaths(string searchFolder) | ||
{ | ||
string[]? filePaths = default; | ||
|
||
try | ||
{ | ||
filePaths = Directory.GetFiles(searchFolder, "*.xaml", SearchOption.AllDirectories); | ||
} | ||
catch (UnauthorizedAccessException uae) | ||
{ | ||
Log.Error( | ||
"An error occurred while retrieving XAML files for processing", | ||
uae); | ||
} | ||
|
||
return filePaths; | ||
} | ||
|
||
private static string GetElementWrapperType(string elementName) | ||
{ | ||
return SupportedUnoPlatformElements.Contains(elementName, SimpleStringComparer) ? elementName : BaseElementType; | ||
} | ||
|
||
private IEnumerable<XElement> FlattenElements(IEnumerable<XElement> elements) | ||
{ | ||
return elements.SelectMany(c => this.FlattenElements(c.Elements())).Concat(elements); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
tools/Legerity.Uno.PageObjectGenerator/Infrastructure/Configuration/Options.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace Legerity.Uno.Infrastructure.Configuration; | ||
|
||
using CommandLine; | ||
|
||
internal class Options | ||
{ | ||
[Option('i', "input", | ||
HelpText = | ||
"The path to the folder where platform pages exist that will be generating page objects for. Default to the executing folder.")] | ||
public string InputPath { get; set; } = @"C:\S\Personal\MADE\legerity-uno\samples\UnoSampleApp\UnoSampleApp\UnoSampleApp.Shared"; | ||
|
||
[Option('o', "output", | ||
HelpText = | ||
"The path to the folder where the generated page object files should be stored. Default to the 'Generated' folder in the executing folder.")] | ||
public string OutputPath { get; set; } = System.IO.Path.Combine(Environment.CurrentDirectory, "Generated"); | ||
|
||
[Option('n', "namespace", | ||
HelpText = | ||
"The namespace to apply to the output page objects. Default to 'LegerityUnoTests.Pages'.")] | ||
public string Namespace { get; set; } = "LegerityUnoTests.Pages"; | ||
} |
11 changes: 11 additions & 0 deletions
11
tools/Legerity.Uno.PageObjectGenerator/Infrastructure/Extensions/StringExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Legerity.Uno.Infrastructure.Extensions; | ||
|
||
using System.Linq; | ||
|
||
internal static class StringExtensions | ||
{ | ||
internal static string Capitalize(this string value) | ||
{ | ||
return value.First().ToString().ToUpper() + value.Substring(1); | ||
} | ||
} |
Oops, something went wrong.