Skip to content

Commit 5ae40e8

Browse files
spike83csantero
authored andcommitted
Feat: context path for api (#114)
* extended JsonApiHttpConfiguration to allow BaseUrlService with configured context path * Feat: context path for api - option to configure context path for api which will be respected in routing and for urls in response - option to configure the public origin address which will be used in response urls closes #112
1 parent ef5cb3c commit 5ae40e8

File tree

15 files changed

+726
-22
lines changed

15 files changed

+726
-22
lines changed

JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/AcceptanceTestsBase.cs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Data.Common;
3+
using System.IO;
34
using System.Net;
45
using System.Net.Http;
56
using System.Text;
@@ -10,6 +11,7 @@
1011
using JSONAPI.Json;
1112
using Microsoft.Owin.Testing;
1213
using Microsoft.VisualStudio.TestTools.UnitTesting;
14+
using Owin;
1315

1416
namespace JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests
1517
{
@@ -20,19 +22,18 @@ public abstract class AcceptanceTestsBase
2022
private static readonly Regex GuidRegex = new Regex(@"\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b", RegexOptions.IgnoreCase);
2123
//private static readonly Regex StackTraceRegex = new Regex(@"""stackTrace"":[\s]*""[\w\:\\\.\s\,\-]*""");
2224
private static readonly Regex StackTraceRegex = new Regex(@"""stackTrace""[\s]*:[\s]*"".*?""");
23-
private static readonly Uri BaseUri = new Uri("https://www.example.com");
25+
protected static Uri BaseUri = new Uri("https://www.example.com");
2426

2527
protected static DbConnection GetEffortConnection()
2628
{
2729
return TestHelpers.GetEffortConnection(@"Data");
2830
}
2931

30-
protected static async Task AssertResponseContent(HttpResponseMessage response, string expectedResponseTextResourcePath, HttpStatusCode expectedStatusCode, bool redactErrorData = false)
32+
protected virtual async Task AssertResponseContent(HttpResponseMessage response, string expectedResponseTextResourcePath, HttpStatusCode expectedStatusCode, bool redactErrorData = false)
3133
{
3234
var responseContent = await response.Content.ReadAsStringAsync();
3335

34-
var expectedResponse =
35-
JsonHelpers.MinifyJson(TestHelpers.ReadEmbeddedFile(expectedResponseTextResourcePath));
36+
var expectedResponse = ExpectedResponse(expectedResponseTextResourcePath);
3637
string actualResponse;
3738
if (redactErrorData)
3839
{
@@ -51,14 +52,21 @@ protected static async Task AssertResponseContent(HttpResponseMessage response,
5152
response.StatusCode.Should().Be(expectedStatusCode);
5253
}
5354

55+
protected virtual string ExpectedResponse(string expectedResponseTextResourcePath)
56+
{
57+
var expectedResponse =
58+
JsonHelpers.MinifyJson(TestHelpers.ReadEmbeddedFile(expectedResponseTextResourcePath));
59+
return expectedResponse;
60+
}
61+
5462
#region GET
5563

5664
protected async Task<HttpResponseMessage> SubmitGet(DbConnection effortConnection, string requestPath)
5765
{
5866
using (var server = TestServer.Create(app =>
5967
{
6068
var startup = new Startup(() => new TestDbContext(effortConnection, false));
61-
startup.Configuration(app);
69+
StartupConfiguration(startup, app);
6270
}))
6371
{
6472
var uri = new Uri(BaseUri, requestPath);
@@ -75,7 +83,7 @@ protected async Task<HttpResponseMessage> SubmitPost(DbConnection effortConnecti
7583
using (var server = TestServer.Create(app =>
7684
{
7785
var startup = new Startup(() => new TestDbContext(effortConnection, false));
78-
startup.Configuration(app);
86+
StartupConfiguration(startup, app);
7987
}))
8088
{
8189
var uri = new Uri(BaseUri, requestPath);
@@ -100,7 +108,7 @@ protected async Task<HttpResponseMessage> SubmitPatch(DbConnection effortConnect
100108
using (var server = TestServer.Create(app =>
101109
{
102110
var startup = new Startup(() => new TestDbContext(effortConnection, false));
103-
startup.Configuration(app);
111+
StartupConfiguration(startup, app);
104112
}))
105113
{
106114
var uri = new Uri(BaseUri, requestPath);
@@ -124,7 +132,7 @@ protected async Task<HttpResponseMessage> SubmitDelete(DbConnection effortConnec
124132
using (var server = TestServer.Create(app =>
125133
{
126134
var startup = new Startup(() => new TestDbContext(effortConnection, false));
127-
startup.Configuration(app);
135+
StartupConfiguration(startup, app);
128136
}))
129137
{
130138
var uri = new Uri(BaseUri, requestPath);
@@ -137,5 +145,22 @@ protected async Task<HttpResponseMessage> SubmitDelete(DbConnection effortConnec
137145
}
138146

139147
#endregion
148+
149+
150+
151+
#region configure startup
152+
153+
/// <summary>
154+
/// Startup process was divided into 4 steps to support better acceptance tests.
155+
/// This method can be overridden by subclass to change behavior of setup.
156+
/// </summary>
157+
/// <param name="startup"></param>
158+
/// <param name="app"></param>
159+
protected virtual void StartupConfiguration(Startup startup, IAppBuilder app)
160+
{
161+
startup.Configuration(app);
162+
}
163+
164+
#endregion
140165
}
141166
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
using System;
2+
using System.Data.SqlTypes;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Text.RegularExpressions;
6+
using System.Threading.Tasks;
7+
using FluentAssertions;
8+
using JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Models;
9+
using JSONAPI.Http;
10+
using Microsoft.VisualStudio.TestTools.UnitTesting;
11+
using Owin;
12+
13+
namespace JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests
14+
{
15+
[TestClass]
16+
public class BaseUrlTest : AcceptanceTestsBase
17+
{
18+
[TestInitialize]
19+
public void TestInit()
20+
{
21+
if (!BaseUri.AbsoluteUri.EndsWith("api/"))
22+
{
23+
BaseUri = new Uri(BaseUri.AbsoluteUri + "api/");
24+
}
25+
}
26+
[TestCleanup]
27+
public void TestCleanup()
28+
{
29+
if (BaseUri.AbsoluteUri.EndsWith("api/"))
30+
{
31+
BaseUri = new Uri(BaseUri.AbsoluteUri.Substring(0,BaseUri.AbsoluteUri.Length -4));
32+
}
33+
}
34+
35+
// custom startup process for this test
36+
protected override void StartupConfiguration(Startup startup, IAppBuilder app)
37+
{
38+
39+
var configuration = startup.BuildConfiguration();
40+
// here we add the custom BaseUrlServcie
41+
configuration.CustomBaseUrlService = new BaseUrlService("api");
42+
var configurator = startup.BuildAutofacConfigurator(app);
43+
var httpConfig = startup.BuildHttpConfiguration();
44+
startup.MergeAndSetupConfiguration(app, configurator, httpConfig, configuration);
45+
}
46+
47+
// custom expected response method
48+
protected override string ExpectedResponse(string expectedResponseTextResourcePath)
49+
{
50+
var expected = base.ExpectedResponse(expectedResponseTextResourcePath);
51+
return Regex.Replace(expected, @"www\.example\.com\/", @"www.example.com/api/");
52+
}
53+
54+
// copied some tests in here
55+
56+
// copied from ComputedIdTests
57+
58+
[TestMethod]
59+
[DeploymentItem(@"Data\Comment.csv", @"Data")]
60+
[DeploymentItem(@"Data\Language.csv", @"Data")]
61+
[DeploymentItem(@"Data\LanguageUserLink.csv", @"Data")]
62+
[DeploymentItem(@"Data\Post.csv", @"Data")]
63+
[DeploymentItem(@"Data\PostTagLink.csv", @"Data")]
64+
[DeploymentItem(@"Data\Tag.csv", @"Data")]
65+
[DeploymentItem(@"Data\User.csv", @"Data")]
66+
public async Task Get_resource_with_computed_id_by_id()
67+
{
68+
using (var effortConnection = GetEffortConnection())
69+
{
70+
var response = await SubmitGet(effortConnection, "language-user-links/9001_402");
71+
72+
await AssertResponseContent(response, @"Fixtures\ComputedId\Responses\Get_resource_with_computed_id_by_id_Response.json", HttpStatusCode.OK);
73+
}
74+
}
75+
76+
77+
// copied from CreatingResourcesTests
78+
79+
80+
[TestMethod]
81+
[DeploymentItem(@"Data\PostLongId.csv", @"Data")]
82+
public async Task PostLongId_with_client_provided_id()
83+
{
84+
using (var effortConnection = GetEffortConnection())
85+
{
86+
var response = await SubmitPost(effortConnection, "post-long-ids", @"Fixtures\CreatingResources\Requests\PostLongId_with_client_provided_id_Request.json");
87+
88+
await AssertResponseContent(response, @"Fixtures\CreatingResources\Responses\PostLongId_with_client_provided_id_Response.json", HttpStatusCode.OK);
89+
90+
using (var dbContext = new TestDbContext(effortConnection, false))
91+
{
92+
var allPosts = dbContext.PostsLongId.ToArray();
93+
allPosts.Length.Should().Be(5);
94+
var actualPost = allPosts.First(t => t.Id == 205);
95+
actualPost.Id.Should().Be(205);
96+
actualPost.Title.Should().Be("Added post");
97+
actualPost.Content.Should().Be("Added post content");
98+
actualPost.Created.Should().Be(new DateTimeOffset(2015, 03, 11, 04, 31, 0, new TimeSpan(0)));
99+
}
100+
}
101+
}
102+
103+
104+
105+
// copied from DeletingResourcesTests
106+
107+
[TestMethod]
108+
[DeploymentItem(@"Data\PostID.csv", @"Data")]
109+
public async Task DeleteID()
110+
{
111+
using (var effortConnection = GetEffortConnection())
112+
{
113+
var response = await SubmitDelete(effortConnection, "post-i-ds/203");
114+
115+
var responseContent = await response.Content.ReadAsStringAsync();
116+
responseContent.Should().Be("");
117+
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
118+
119+
using (var dbContext = new TestDbContext(effortConnection, false))
120+
{
121+
var allPosts = dbContext.PostsID.ToArray();
122+
allPosts.Length.Should().Be(3);
123+
var actualPosts = allPosts.FirstOrDefault(t => t.ID == "203");
124+
actualPosts.Should().BeNull();
125+
}
126+
}
127+
}
128+
129+
130+
131+
// copied from FetchingResourcesTests
132+
133+
[TestMethod]
134+
[DeploymentItem(@"Data\Comment.csv", @"Data")]
135+
[DeploymentItem(@"Data\Post.csv", @"Data")]
136+
[DeploymentItem(@"Data\PostTagLink.csv", @"Data")]
137+
[DeploymentItem(@"Data\Tag.csv", @"Data")]
138+
[DeploymentItem(@"Data\User.csv", @"Data")]
139+
public async Task GetWithFilter()
140+
{
141+
using (var effortConnection = GetEffortConnection())
142+
{
143+
var response = await SubmitGet(effortConnection, "posts?filter[title]=Post 4");
144+
145+
await AssertResponseContent(response, @"Fixtures\FetchingResources\GetWithFilterResponse.json", HttpStatusCode.OK);
146+
}
147+
}
148+
149+
[TestMethod]
150+
[DeploymentItem(@"Data\Comment.csv", @"Data")]
151+
[DeploymentItem(@"Data\Post.csv", @"Data")]
152+
[DeploymentItem(@"Data\PostTagLink.csv", @"Data")]
153+
[DeploymentItem(@"Data\Tag.csv", @"Data")]
154+
[DeploymentItem(@"Data\User.csv", @"Data")]
155+
public async Task GetById()
156+
{
157+
using (var effortConnection = GetEffortConnection())
158+
{
159+
var response = await SubmitGet(effortConnection, "posts/202");
160+
161+
await AssertResponseContent(response, @"Fixtures\FetchingResources\GetByIdResponse.json", HttpStatusCode.OK);
162+
}
163+
}
164+
165+
}
166+
}

JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests.csproj

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
<Reference Include="Microsoft.Owin.Testing">
6262
<HintPath>..\packages\Microsoft.Owin.Testing.3.0.0\lib\net45\Microsoft.Owin.Testing.dll</HintPath>
6363
</Reference>
64+
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
65+
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
66+
<Private>True</Private>
67+
</Reference>
6468
<Reference Include="NMemory">
6569
<HintPath>..\packages\NMemory.1.0.1\lib\net45\NMemory.dll</HintPath>
6670
</Reference>
@@ -71,7 +75,15 @@
7175
<Reference Include="System.ComponentModel.DataAnnotations" />
7276
<Reference Include="System.Data" />
7377
<Reference Include="System.Net.Http" />
78+
<Reference Include="System.Net.Http.Formatting, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
79+
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll</HintPath>
80+
<Private>True</Private>
81+
</Reference>
7482
<Reference Include="System.Transactions" />
83+
<Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
84+
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll</HintPath>
85+
<Private>True</Private>
86+
</Reference>
7587
<Reference Include="System.Xml" />
7688
<Reference Include="System.Xml.Linq" />
7789
</ItemGroup>
@@ -98,6 +110,7 @@
98110
<Compile Include="HeterogeneousTests.cs" />
99111
<Compile Include="MappedTests.cs" />
100112
<Compile Include="Properties\AssemblyInfo.cs" />
113+
<Compile Include="BaseUrlTest.cs" />
101114
<Compile Include="SortingTests.cs" />
102115
<Compile Include="TestHelpers.cs" />
103116
<Compile Include="UpdatingResourcesTests.cs" />
@@ -107,6 +120,10 @@
107120
<Project>{76dee472-723b-4be6-8b97-428ac326e30f}</Project>
108121
<Name>JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp</Name>
109122
</ProjectReference>
123+
<ProjectReference Include="..\JSONAPI.Autofac\JSONAPI.Autofac.csproj">
124+
<Project>{AF7861F3-550B-4F70-A33E-1E5F48D39333}</Project>
125+
<Name>JSONAPI.Autofac</Name>
126+
</ProjectReference>
110127
<ProjectReference Include="..\JSONAPI\JSONAPI.csproj">
111128
<Project>{52b19fd6-efaa-45b5-9c3e-a652e27608d1}</Project>
112129
<Name>JSONAPI</Name>

JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests/packages.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
<package id="Effort.EF6" version="1.1.4" targetFramework="net45" />
44
<package id="EntityFramework" version="6.1.3" targetFramework="net45" />
55
<package id="FluentAssertions" version="3.2.2" targetFramework="net45" />
6+
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net45" />
7+
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net45" />
68
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" />
79
<package id="Microsoft.Owin.Hosting" version="3.0.0" targetFramework="net45" />
810
<package id="Microsoft.Owin.Testing" version="3.0.0" targetFramework="net45" />
11+
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
912
<package id="NMemory" version="1.0.1" targetFramework="net45" />
1013
<package id="Owin" version="1.0" targetFramework="net45" />
1114
</packages>

JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection;
2+
using System.Runtime.CompilerServices;
23
using System.Runtime.InteropServices;
34

45
// General Information about an assembly is controlled through the following
@@ -32,3 +33,4 @@
3233
// by using the '*' as shown below:
3334
[assembly: AssemblyVersion("1.0.0.0")]
3435
[assembly: AssemblyFileVersion("1.0.0.0")]
36+
[assembly: InternalsVisibleTo("JSONAPI.AcceptanceTests.EntityFrameworkTestWebApp.Tests")]

0 commit comments

Comments
 (0)