Skip to content

Commit 40f2529

Browse files
authored
Merge pull request #155 from octokit/readable-expressions-tests
Readable expressions tests
2 parents cfd50d9 + 53d50e9 commit 40f2529

File tree

10 files changed

+473
-307
lines changed

10 files changed

+473
-307
lines changed

Octokit.GraphQL.Core.UnitTests/ExpressionRewiterTests.cs

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
43
using System.Linq;
54
using System.Linq.Expressions;
@@ -20,21 +19,20 @@ public ExpressionRewiterTests()
2019
[Fact]
2120
public void Repository_Select_Single_Member()
2221
{
23-
var expression = new Query()
22+
var query = new Query()
2423
.Repository("foo", "bar")
2524
.Select(x => x.Name);
2625

2726
Expression<Func<JObject, string>> expected = data =>
2827
Rewritten.Value.Select(data["data"]["repository"], x => x["name"]).ToObject<string>();
2928

30-
var query = expression.Compile();
31-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
29+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
3230
}
3331

3432
[Fact]
3533
public void Repository_Select_Multiple_Members()
3634
{
37-
var expression = new Query()
35+
var query = new Query()
3836
.Repository("foo", "bar")
3937
.Select(x => new { x.Name, x.Description });
4038

@@ -45,14 +43,13 @@ public void Repository_Select_Multiple_Members()
4543
Description = x["description"].ToObject<string>(),
4644
});
4745

48-
var query = expression.Compile();
49-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
46+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
5047
}
5148

5249
[Fact]
5350
public void Repository_Issues_Select_Multiple_Members()
5451
{
55-
var expression = new Query()
52+
var query = new Query()
5653
.Repository("foo", "bar")
5754
.Issues(10)
5855
.Nodes
@@ -65,14 +62,13 @@ public void Repository_Issues_Select_Multiple_Members()
6562
Closed = x["closed"].ToObject<bool>(),
6663
}).ToList();
6764

68-
var query = expression.Compile();
69-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
65+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
7066
}
7167

7268
[Fact]
7369
public void Licence_Conditions_Nested_Selects()
7470
{
75-
var expression = new Query()
71+
var query = new Query()
7672
.Licenses
7773
.Select(x => new
7874
{
@@ -89,14 +85,13 @@ public void Licence_Conditions_Nested_Selects()
8985
Items = Rewritten.List.ToList<string>(Rewritten.List.Select(x["items"], i => i["description"]))
9086
}).ToList();
9187

92-
var query = expression.Compile();
93-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
88+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
9489
}
9590

9691
[Fact]
9792
public void Licenses_Conditions_Select_ToDictionary()
9893
{
99-
var expression = new Query()
94+
var query = new Query()
10095
.Licenses
10196
.Select(x => new
10297
{
@@ -114,23 +109,20 @@ public void Licenses_Conditions_Select_ToDictionary()
114109
x => new
115110
{
116111
Body = x["body"].ToObject<string>(),
117-
Items = (IDictionary<string, object>) Rewritten.List.Select(x["items"], i => new
112+
Items = (IDictionary<string, string>) Rewritten.List.Select(x["items"], i => new
118113
{
119114
Key = i["key"].ToObject<string>(),
120115
Description = i["description"].ToObject<string>()
121116
}).ToDictionary(d => d.Key, d => d.Description)
122117
}).ToList();
123118

124-
var query = expression.Compile();
125-
var expectedString = expected.ToString();
126-
var actual = query.GetResultBuilderExpression().ToString();
127-
Assert.Equal(expectedString, actual);
119+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
128120
}
129121

130122
[Fact]
131123
public void Issue_Milestone_Select_Value_Single()
132124
{
133-
var expression = new Query()
125+
var query = new Query()
134126
.Repository("foo", "bar")
135127
.Issue(1)
136128
.Select(x => new
@@ -143,7 +135,7 @@ public void Issue_Milestone_Select_Value_Single()
143135
});
144136

145137
Expression<Func<JObject, object>> expected = data =>
146-
Rewritten.List.Select(
138+
Rewritten.Value.Select(
147139
data["data"]["repository"]["issue"],
148140
x => new
149141
{
@@ -157,14 +149,13 @@ public void Issue_Milestone_Select_Value_Single()
157149
}))
158150
});
159151

160-
var query = expression.Compile();
161-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
152+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
162153
}
163154

164155
[Fact]
165156
public void Issue_Milestone_Select_Value_SingleOrDefault()
166157
{
167-
var expression = new Query()
158+
var query = new Query()
168159
.Repository("foo", "bar")
169160
.Issue(1)
170161
.Select(x => new
@@ -177,7 +168,7 @@ public void Issue_Milestone_Select_Value_SingleOrDefault()
177168
});
178169

179170
Expression<Func<JObject, object>> expected = data =>
180-
Rewritten.List.Select(
171+
Rewritten.Value.Select(
181172
data["data"]["repository"]["issue"],
182173
x => new
183174
{
@@ -191,14 +182,13 @@ public void Issue_Milestone_Select_Value_SingleOrDefault()
191182
}))
192183
});
193184

194-
var query = expression.Compile();
195-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
185+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
196186
}
197187

198188
[Fact]
199189
public void Nodes_OfType()
200190
{
201-
var expression = new Query()
191+
var query = new Query()
202192
.Nodes(new[] { new ID("123") })
203193
.OfType<Issue>()
204194
.Select(x => new
@@ -214,14 +204,13 @@ public void Nodes_OfType()
214204
Body = x["body"].ToObject<string>(),
215205
}).ToList();
216206

217-
var query = expression.Compile();
218-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
207+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
219208
}
220209

221210
[Fact]
222211
public void Node_OfType()
223212
{
224-
var expression = new Query()
213+
var query = new Query()
225214
.Node(new ID("123"))
226215
.Cast<Issue>()
227216
.Select(x => x.Body);
@@ -231,14 +220,13 @@ public void Node_OfType()
231220
Rewritten.Interface.Cast(data["data"]["node"], "Issue"),
232221
x => x["body"]).ToObject<string>();
233222

234-
var query = expression.Compile();
235-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
223+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
236224
}
237225

238226
[Fact]
239227
public void Can_Use_Conditional_With_Null_Result()
240228
{
241-
var expression = new Query()
229+
var query = new Query()
242230
.Repository("foo", "bar")
243231
.Select(x => !string.IsNullOrWhiteSpace(x.Name) ? x.Name : null);
244232

@@ -247,29 +235,28 @@ public void Can_Use_Conditional_With_Null_Result()
247235
data["data"]["repository"],
248236
x => !string.IsNullOrWhiteSpace(x["name"].ToObject<string>()) ? x["name"].ToObject<string>() : null);
249237

250-
var query = expression.Compile();
251-
Assert.Equal(expected.ToString(), query.GetResultBuilderExpression().ToString());
238+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(expected, query);
252239
}
253240

254241
[Fact]
255242
public void Can_Use_Conditional_To_Compare_To_Null()
256243
{
257-
var expression = new Query()
244+
var query = new Query()
258245
.Repository("foo", "bar")
259246
.Select(x => x.Name != null ? x.Name : null);
260247

261-
// C# inserts a Convert() around the comparison in the following expression, making the test fail.
262-
//
263248
// Expression<Func<JObject, object>> expected = data =>
264249
// Rewritten.Value.Select(
265250
// data["data"]["repository"],
266-
// x => x["name"].Type != JTokenType.Null ? x["name"] : null).ToObject<string>();
267-
//
268-
// Just hardcode the expected output.
269-
var expected = "data => Select(data.get_Item(\"data\").get_Item(\"repository\"), x => IIF((x.get_Item(\"name\").Type != Null), x.get_Item(\"name\").ToObject(), null))";
251+
// x => x["name"].Type != JTokenType.Null ? x["name"].ToObject<string>() : null);
252+
253+
var readableString =
254+
"data => Rewritten.Value.Select(data[\"data\"][\"repository\"],x => (x[\"name\"].Type != JTokenType.Null) ? x[\"name\"].ToObject<string>() : null)";
255+
256+
// Expression put through ReadableExpression outputs the following, so I'm using a hard coded string instead
257+
// data => Rewritten.Value.Select(data["data"]["repository"], x => (((int)x["name"].Type) != 10) ? x["name"].ToObject<string>() : null)
270258

271-
var query = expression.Compile();
272-
Assert.Equal(expected, query.GetResultBuilderExpression().ToString());
259+
ExpressionRewriterAssertions.AssertExpressionQueryEqual(readableString, query);
273260
}
274261
}
275262
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq.Expressions;
4+
using System.Text.RegularExpressions;
5+
using AgileObjects.ReadableExpressions;
6+
using Newtonsoft.Json.Linq;
7+
using Octokit.GraphQL.Core.Builders;
8+
using Xunit;
9+
10+
namespace Octokit.GraphQL.Core.UnitTests
11+
{
12+
public static class ExpressionRewriterAssertions
13+
{
14+
private const string AnonymousType = "AnonymousType";
15+
private static readonly int AnonymousTypeLength = AnonymousType.Length;
16+
17+
public static void AssertExpressionQueryEqual<T>(Expression expected, IQueryableValue<T> actual)
18+
{
19+
var actualCompiledQuery = actual.Compile();
20+
AssertCompiledQueryExpressionEqual(expected, actualCompiledQuery);
21+
}
22+
23+
public static void AssertExpressionQueryEqual<T>(Expression expected, IQueryableList<T> actual)
24+
{
25+
var actualCompiledQuery = actual.Compile();
26+
AssertCompiledQueryExpressionEqual(expected, actualCompiledQuery);
27+
}
28+
29+
public static void AssertExpressionQueryEqual<T>(string expectedString, IQueryableValue<T> actual)
30+
{
31+
var actualCompiledQuery = actual.Compile();
32+
AssertCompiledQueryExpressionEqual(expectedString, actualCompiledQuery);
33+
}
34+
35+
public static void AssertCompiledQueryExpressionEqual<T>(Expression expected, ICompiledQuery<T> actualCompiledQuery, params string[] subqueryPlaceholderReplacements)
36+
{
37+
var expectedString = expected.ToReadableString();
38+
AssertCompiledQueryExpressionEqual(expectedString, actualCompiledQuery, subqueryPlaceholderReplacements);
39+
}
40+
41+
public static void AssertCompiledQueryExpressionEqual<T>(string expectedString, ICompiledQuery<T> actualCompiledQuery, params string[] subqueryPlaceholderReplacements)
42+
{
43+
var actualResultExpression = actualCompiledQuery.GetResultBuilderExpression();
44+
var actualString = actualResultExpression.ToReadableString(settings => settings.NameAnonymousTypesUsing(_ => "object"));
45+
46+
expectedString = ReplaceSubqueryPlaceholders(expectedString, subqueryPlaceholderReplacements);
47+
48+
Assert.Equal(StripWhitespace(expectedString), StripWhitespace(actualString));
49+
}
50+
51+
public static string ReplaceSubqueryPlaceholders(string expectedString, params string[] subqueryPlaceholderReplacements)
52+
{
53+
foreach (var subqueryPlaceholderReplacement in subqueryPlaceholderReplacements)
54+
{
55+
var regex = new Regex("PagingTests.subqueryPlaceholder");
56+
expectedString = regex.Replace(expectedString, subqueryPlaceholderReplacement, 1);
57+
}
58+
59+
return expectedString;
60+
}
61+
62+
public static string StripWhitespace(string x)
63+
{
64+
return x.Replace(" ", string.Empty).Replace("\r", string.Empty).Replace("\n", string.Empty);
65+
}
66+
67+
public static void AssertSubqueryEqual<T>(Expression<Func<JObject, T>> expectedResultExpression,
68+
Expression<Func<JObject, JToken>> expectedPageInfoExpression,
69+
Expression<Func<JObject, IEnumerable<JToken>>> expectedParentIdExpression,
70+
Expression<Func<JObject, IEnumerable<JToken>>> expectedParentPageInfoExpression,
71+
PagedSubquery<T> subquery)
72+
{
73+
var resultExpression = ExpressionCompiler.GetSourceExpression(subquery.MasterQuery.ResultBuilder);
74+
Assert.Equal(StripWhitespace(expectedResultExpression.ToReadableString()), StripWhitespace(resultExpression.ToReadableString()));
75+
76+
var pageInfoExpression = ExpressionCompiler.GetSourceExpression(subquery.PageInfo);
77+
Assert.Equal(StripWhitespace(expectedPageInfoExpression.ToReadableString()), StripWhitespace(pageInfoExpression.ToReadableString()));
78+
79+
var parentIdExpression = ExpressionCompiler.GetSourceExpression(subquery.ParentIds);
80+
Assert.Equal(StripWhitespace(expectedParentIdExpression.ToReadableString()), StripWhitespace(parentIdExpression.ToReadableString()));
81+
82+
var parentPageInfoExpression = ExpressionCompiler.GetSourceExpression(subquery.ParentPageInfo);
83+
Assert.Equal(StripWhitespace(expectedParentPageInfoExpression.ToReadableString()), StripWhitespace(parentPageInfoExpression.ToReadableString()));
84+
}
85+
}
86+
}

Octokit.GraphQL.Core.UnitTests/Octokit.GraphQL.Core.UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<LangVersion>7.2</LangVersion>
55
</PropertyGroup>
66
<ItemGroup>
7+
<PackageReference Include="AgileObjects.ReadableExpressions" Version="1.12.1" />
78
<PackageReference Include="BCC-MSBuildLog" Version="0.0.2-alpha" />
89
<PackageReference Include="BCC-Submission" Version="0.0.2-alpha" />
910
<PackageReference Include="coverlet.msbuild" Version="2.2.1">

0 commit comments

Comments
 (0)