Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fixes incomplete snippets with expand query options and filter query options that use function operator types #1646

30 changes: 29 additions & 1 deletion CodeSnippetsReflection.OpenAPI.Test/GraphCliGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,34 @@ public async Task GeneratesSnippetsWithSlashMeEndpoints()
var result = _generator.GenerateCodeSnippet(snippetModel);

// Then
Assert.Equal("mgc users calendar events list --user-id {user-id} --filter startsWith(subject,'All')", result);
Assert.Equal("mgc users calendar events list --user-id {user-id} --filter \"startsWith(subject,'All')\"", result);
}
[Fact]
public async Task GeneratesSnippetsWithExpandQueryOptions()
{
// Given
string url = $"{ServiceRootUrl}/me/messages/XXXX?$expand=singleValueExtendedProperties%28$filter%3Did%20eq%20%27XXXX%27%29";
using var requestPayload = new HttpRequestMessage(HttpMethod.Get, url);
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());

// When
var result = _generator.GenerateCodeSnippet(snippetModel);

// Then
Assert.Equal("mgc users messages get --user-id {user-id} --message-id {message-id} --expand \"singleValueExtendedProperties(`$filter=id eq 'XXXX')\"", result);
}
[Fact]
public async Task GeneratesSnippetsWithFilterQueryOptions()
{
// Given
string url = $"{ServiceRootUrl}/identityGovernance/accessReviews/definitions?$filter=contains%28scope%2Fmicrosoft.graph.accessReviewQueryScope%2Fquery%2C%20%27.%2Fmembers%27%29";
using var requestPayload = new HttpRequestMessage(HttpMethod.Get, url);
var snippetModel = new SnippetModel(requestPayload, ServiceRootUrl, await GetV1SnippetMetadata());

// When
var result = _generator.GenerateCodeSnippet(snippetModel);

// Then
Assert.Equal("mgc identity-governance access-reviews definitions list --filter \"contains(scope/microsoft.graph.accessReviewQueryScope/query, './members')\"", result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public partial class GraphCliGenerator : ILanguageGenerator<SnippetModel, OpenAp
private static readonly Regex overloadedBoundedFunctionWithNoneDateRegex = new(@"\w*\(\w*='{\w*\}'\)", RegexOptions.Compiled, TimeSpan.FromSeconds(5));
private static readonly Regex apiPathWithSingleOrDoubleQuotesOnFunctions = new(@"(\/\w+)+\(\w*=(?:'|"").*(?:'|"")\)", RegexOptions.Compiled, TimeSpan.FromSeconds(5));
private static readonly Regex unBoundFunctionRegex = new(@"^[0-9a-zA-Z\- \/_?:.,\s]+\(\)", RegexOptions.Compiled, TimeSpan.FromSeconds(5));
private static readonly Regex systemQueryOptionRegex = new(@"\w*=\w*\(\D*|\d*\)", RegexOptions.Compiled, TimeSpan.FromSeconds(5));

private const string PathItemsKey = "default";

Expand Down Expand Up @@ -220,16 +221,29 @@ private static IDictionary<string, string> ProcessQueryParameters([NotNull] in S
IDictionary<string, string> splitQueryString = new Dictionary<string, string>();
if (!string.IsNullOrWhiteSpace(snippetModel.QueryString))
{
splitQueryString = snippetModel.QueryString
.Remove(0, 1)
.Split('&')
.Select(q =>
{
var x = q.Split('=');
return x.Length > 1 ? (x[0], x[1]) : (x[0], string.Empty);
})
.Where(t => !string.IsNullOrWhiteSpace(t.Item2))
.ToDictionary(t => t.Item1, t => t.Item2);
if (systemQueryOptionRegex.IsMatch(snippetModel.QueryString))
{
string pattern = "\\?\\$\\w*=";
string[] splittedQueryString = Regex.Split(snippetModel.QueryString, pattern, RegexOptions.Compiled, TimeSpan.FromSeconds(5));
var match = Regex.Match(snippetModel.QueryString, pattern, RegexOptions.Compiled, TimeSpan.FromSeconds(5));
string queryOption = match.Groups[0].Value.Replace("?", string.Empty, StringComparison.OrdinalIgnoreCase).Replace("=", string.Empty, StringComparison.OrdinalIgnoreCase);
string queryOptionFunction = splittedQueryString[1].Replace("$", "`$", StringComparison.OrdinalIgnoreCase);
queryOptionFunction = queryOptionFunction.Replace(queryOptionFunction, "\"" + queryOptionFunction + "\"", StringComparison.Ordinal);
splitQueryString.Add(queryOption, queryOptionFunction);
}
else
{
splitQueryString = snippetModel.QueryString
.Remove(0, 1)
.Split('&')
.Select(static q =>
{
var x = q.Split('=');
return x.Length > 1 ? (x[0], x[1]) : (x[0], string.Empty);
})
.Where(static t => !string.IsNullOrWhiteSpace(t.Item2))
.ToDictionary(static t => t.Item1, static t => t.Item2);
}
}

return splitQueryString;
Expand Down