-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
+semver: minor
- Loading branch information
Showing
13 changed files
with
238 additions
and
108 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 |
---|---|---|
|
@@ -115,12 +115,22 @@ Given I have created 'a record' | |
``` | ||
or | ||
```gherkin | ||
Given 'someone' has created 'a record' | ||
Given 'someone' has created 'a record with a difference' | ||
``` | ||
|
||
The examples above will both look for a JSON file named _a record.json_ in the _data_ folder (you must ensure that these files are copying to the build output directory). The difference is that the latter requires the following in the configuration file: | ||
These bindings look for a corresponding JSON file in a _data_ folder in the root of your project. The file is resolved using a combination of the directory structure and the file name. For example, the bindings above could resolve the following files: | ||
|
||
- a user with an alias of _someone_ in the `users` array | ||
``` | ||
└───data | ||
│ a record.json | ||
│ | ||
└───a record | ||
with a difference.json | ||
``` | ||
|
||
If you are using the binding which creates data as someone other than the current user, you will need the following configuration to be present: | ||
|
||
- a user with a matching alias in the `users` array that has the `username` set | ||
- an application user with sufficient privileges to impersonate the above user configured in the `applicationUser` property. | ||
|
||
Refer to the Microsoft documentation on creating an application user [here](https://docs.microsoft.com/en-us/power-platform/admin/create-users-assign-online-security-roles#create-an-application-user). | ||
|
@@ -153,25 +163,17 @@ The example above will create the following: | |
- An opportunity related to the account | ||
- A task related to the opportunity | ||
|
||
The `@logicalName` property is required for the root record. | ||
In addition to the standard Web API syntax, we also have the following: | ||
|
||
The `@alias` property can optionally be added to any record and allows the record to be referenced in certain bindings. The _Given I have created_ binding itself supports relating records using `@alias.bind` syntax, as shown below: | ||
|
||
```json | ||
{ | ||
"@logicalName": "account", | ||
"@alias": "sample account", | ||
"name": "Sample Account", | ||
"[email protected]": "sample contact" | ||
} | ||
``` | ||
| Property | Description | Requirement | | ||
|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------| | ||
| @logicalName | the entity logical name of the root record | Mandatory (unless included using `@extends` - see below) | | ||
| @alias | a friendly alias that can be used to reference the created record in certain bindings. Can be set on nested records | Optional | | ||
| @extends | a relative path to a data file to extend. Records in arrays are merged by index (you may need to include blank objects to insert new records into the array) | Optional | | ||
|
||
#### Dynamic data | ||
|
||
We also support the use of | ||
[faker.js](https://github.com/marak/Faker.js) moustache template syntax for generating dynamic test data at run-time. Please refer to the faker documentation for all of the functionality that is available. | ||
|
||
The below JSON will generate a contact with a random name, credit limit, email address, and date of birth in the past 90 years: | ||
We support [faker.js](https://github.com/marak/Faker.js) moustache template syntax for generating dynamic test data at run-time. Please refer to the faker documentation for all of the functionality that is available. The below JSON will generate a contact with a random name, credit limit, email address, and date of birth in the past 90 years: | ||
|
||
```json | ||
{ | ||
|
@@ -181,12 +183,16 @@ The below JSON will generate a contact with a random name, credit limit, email a | |
"firstname": "{{name.lastName}}", | ||
"[email protected]": "{{finance.amount}}", | ||
"emailaddress1": "{{internet.email}}", | ||
"[email protected]": "{{date.past(90)}}" | ||
"[email protected]": "{{date.past(90)}}", | ||
"[email protected]": "sample account" | ||
} | ||
``` | ||
|
||
When using faker syntax, you must also annotate number or date fields using `@faker.number`, `@faker.date` or `@faker.dateonly` to ensure that the JSON is formatted correctly. | ||
|
||
You can also dynamically set lookups by alias using `<lookup>@alias.bind` (this is limited to aliased records in other files - not the current file). | ||
|
||
|
||
## Contributing | ||
|
||
Please refer to the [Contributing](./CONTRIBUTING.md) guide. | ||
|
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,4 @@ | ||
[*.cs] | ||
|
||
# SA1633: File should have header | ||
dotnet_diagnostic.SA1633.severity = none |
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.
21 changes: 21 additions & 0 deletions
21
...ni.PowerApps.SpecFlowBindings.MSBuild/Capgemini.PowerApps.SpecFlowBindings.MSBuild.csproj
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 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> | ||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.8.0" /> | ||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> | ||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.1"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118"> | ||
<PrivateAssets>all</PrivateAssets> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
</Project> |
123 changes: 123 additions & 0 deletions
123
bindings/src/Capgemini.PowerApps.SpecFlowBindings.MSBuild/ExtendDataFiles.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,123 @@ | ||
namespace Capgemini.PowerApps.SpecFlowBindings.MSBuild | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Build.Utilities; | ||
using Newtonsoft.Json.Linq; | ||
|
||
/// <summary> | ||
/// Extend JSON data files using the "@extends" property. | ||
/// </summary> | ||
public class ExtendDataFiles : Task | ||
{ | ||
private const string ExtendsProperty = "@extends"; | ||
|
||
private JsonMergeSettings jsonMergeSettings; | ||
|
||
/// <summary> | ||
/// Gets or sets the items to be extended. | ||
/// </summary> | ||
/// <value> | ||
/// The items to be extended. | ||
/// </value> | ||
[Required] | ||
public ITaskItem[] Include { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the path to output compiled data files to. | ||
/// </summary> | ||
/// <value> | ||
/// The path to output compiled data files to. | ||
/// </value> | ||
[Required] | ||
public ITaskItem DestinationFolder { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets a value indicating how to handle the merging of arrays <see cref="MergeArrayHandling"/>. | ||
/// </summary> | ||
public string ArrayHandling { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the parsed <see cref="MergeArrayHandling"/> value to use. | ||
/// </summary> | ||
/// <value> | ||
/// The parsed <see cref="MergeArrayHandling"/> value to use. | ||
/// </value> | ||
protected MergeArrayHandling MergeArrayHandling => !string.IsNullOrEmpty(this.ArrayHandling) ? (MergeArrayHandling)Enum.Parse(typeof(MergeArrayHandling), this.ArrayHandling) : MergeArrayHandling.Merge; | ||
|
||
private JsonMergeSettings JsonMergeSettings | ||
{ | ||
get | ||
{ | ||
if (this.jsonMergeSettings == null) | ||
{ | ||
this.jsonMergeSettings = new JsonMergeSettings | ||
{ | ||
MergeArrayHandling = this.MergeArrayHandling, | ||
MergeNullValueHandling = MergeNullValueHandling.Merge, | ||
PropertyNameComparison = StringComparison.InvariantCultureIgnoreCase, | ||
}; | ||
} | ||
|
||
return this.jsonMergeSettings; | ||
} | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override bool Execute() | ||
{ | ||
var succeeded = true; | ||
|
||
Directory.CreateDirectory(this.DestinationFolder.ItemSpec); | ||
|
||
foreach (var taskItem in this.Include) | ||
{ | ||
this.CompileDataFile(taskItem.ItemSpec); | ||
} | ||
|
||
return succeeded; | ||
} | ||
|
||
private void CompileDataFile(string itemPath) | ||
{ | ||
this.Log.LogMessage(MessageImportance.Normal, $"Processing data file at '{itemPath}'."); | ||
|
||
var mergeStack = this.GetMergeStack(itemPath); | ||
var rootJson = mergeStack.Pop(); | ||
while (mergeStack.Count > 0) | ||
{ | ||
rootJson.Merge(mergeStack.Pop(), this.JsonMergeSettings); | ||
} | ||
|
||
rootJson.Property(ExtendsProperty)?.Remove(); | ||
|
||
File.WriteAllText(this.GetFileOutputPath(itemPath), rootJson.ToString()); | ||
} | ||
|
||
private string GetFileOutputPath(string itemPath) | ||
{ | ||
return Path.Combine(this.DestinationFolder.ItemSpec, string.Join(" ", itemPath.Split('\\').Skip(1))); | ||
} | ||
|
||
private Stack<JObject> GetMergeStack(string itemPath, Stack<JObject> existingStack = null) | ||
{ | ||
var stack = existingStack ?? new Stack<JObject>(); | ||
var data = JObject.Parse(File.ReadAllText(itemPath)); | ||
stack.Push(data); | ||
|
||
var extends = data[ExtendsProperty]?.ToString(); | ||
if (!string.IsNullOrEmpty(extends)) | ||
{ | ||
this.Log.LogMessage(MessageImportance.Low, $"Adding {extends} to merge stack."); | ||
this.GetMergeStack( | ||
Path.Combine(Path.GetDirectoryName(itemPath), $"{extends}.json"), | ||
stack); | ||
} | ||
|
||
return stack; | ||
} | ||
} | ||
} |
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
Oops, something went wrong.