Skip to content

Commit 8840775

Browse files
Add first test set
1 parent 1a8feac commit 8840775

File tree

2 files changed

+237
-1
lines changed

2 files changed

+237
-1
lines changed

Modules/Authentication.Web/Controllers/SetupController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public async Task<IHandlerBuilder> Index(string user, string password, IRequest
3535

3636
await PerformSetup(request, user, password);
3737

38-
return Redirect.To("{web-auth}/", true);
38+
return Redirect.To("{login}/", true);
3939
}
4040

4141
private IHandlerBuilder RenderSetup(string? username = null, string? errorMessage = null, ResponseStatus? status = null)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Net.Http;
6+
using System.Threading.Tasks;
7+
8+
using GenHTTP.Api.Content.Authentication;
9+
using GenHTTP.Api.Protocol;
10+
11+
using GenHTTP.Modules.Authentication.Web;
12+
using GenHTTP.Modules.IO;
13+
using GenHTTP.Modules.Layouting;
14+
15+
using Microsoft.VisualStudio.TestTools.UnitTesting;
16+
17+
namespace GenHTTP.Testing.Acceptance.Modules.Authentication.Web
18+
{
19+
20+
[TestClass]
21+
public sealed class WebAuthenticationTests
22+
{
23+
24+
#region Tests
25+
26+
[TestMethod]
27+
public async Task TestHappyPath()
28+
{
29+
using var host = GetHost();
30+
31+
await Post(host, "/setup/", "u", "p");
32+
33+
await Post(host, "/login/", "u", "p");
34+
35+
var content = await host.GetResponseAsync("/content/");
36+
37+
await content.AssertStatusAsync(HttpStatusCode.OK);
38+
39+
Assert.AreEqual("Hello World", await content.GetContentAsync());
40+
}
41+
42+
[TestMethod]
43+
public async Task TestSetupEnforced()
44+
{
45+
using var host = GetHost();
46+
47+
using var response = await host.GetResponseAsync("/content");
48+
49+
await response.AssertStatusAsync(HttpStatusCode.TemporaryRedirect);
50+
51+
Assert.IsTrue(response.GetHeader("Location")?.EndsWith("/setup/"));
52+
}
53+
54+
[TestMethod]
55+
public async Task TestLoginRequired()
56+
{
57+
var integration = new TestIntegration().AddUser("a", "b");
58+
59+
using var host = GetHost(integration);
60+
61+
using var response = await host.GetResponseAsync("/content");
62+
63+
await response.AssertStatusAsync(HttpStatusCode.TemporaryRedirect);
64+
65+
Assert.IsTrue(response.GetHeader("Location")?.EndsWith("/login/"));
66+
}
67+
68+
[TestMethod]
69+
public async Task TestSetupFormRenders()
70+
{
71+
using var host = GetHost();
72+
73+
using var response = await host.GetResponseAsync("/setup/");
74+
75+
await response.AssertStatusAsync(HttpStatusCode.OK);
76+
77+
var content = await response.GetContentAsync();
78+
79+
AssertX.Contains("id=\"user\"", content);
80+
}
81+
82+
[TestMethod]
83+
public async Task TestLoginFormRenders()
84+
{
85+
var integration = new TestIntegration().AddUser("a", "b");
86+
87+
using var host = GetHost(integration);
88+
89+
using var response = await host.GetResponseAsync("/login/");
90+
91+
await response.AssertStatusAsync(HttpStatusCode.Unauthorized);
92+
93+
var content = await response.GetContentAsync();
94+
95+
AssertX.Contains("id=\"user\"", content);
96+
}
97+
98+
[TestMethod]
99+
public async Task TestSuccessfulSetupRedirectsToLogin()
100+
{
101+
using var host = GetHost();
102+
103+
using var response = await Post(host, "/setup/", "u", "p");
104+
105+
await response.AssertStatusAsync(HttpStatusCode.RedirectMethod);
106+
107+
var content = await response.GetContentAsync();
108+
109+
Assert.IsTrue(response.GetHeader("Location")?.EndsWith("/login/"));
110+
}
111+
112+
[TestMethod]
113+
public async Task TestCannotSetupWithBadParams()
114+
{
115+
using var host = GetHost();
116+
117+
using var response = await Post(host, "/setup/", "", "");
118+
119+
await response.AssertStatusAsync(HttpStatusCode.BadRequest);
120+
}
121+
122+
[TestMethod]
123+
public async Task TestCannotLoginWithBadParams()
124+
{
125+
var integration = new TestIntegration().AddUser("a", "b");
126+
127+
using var host = GetHost(integration);
128+
129+
using var response = await Post(host, "/login/", "", "");
130+
131+
await response.AssertStatusAsync(HttpStatusCode.BadRequest);
132+
}
133+
134+
[TestMethod]
135+
public async Task TestCannotLoginWithWrongPassword()
136+
{
137+
var integration = new TestIntegration().AddUser("a", "b");
138+
139+
using var host = GetHost(integration);
140+
141+
using var response = await Post(host, "/login/", "a", "c");
142+
143+
await response.AssertStatusAsync(HttpStatusCode.Forbidden);
144+
}
145+
146+
#endregion
147+
148+
#region Test setup
149+
150+
private async Task<HttpResponseMessage> Post(TestHost host, string route, string username, string password)
151+
{
152+
var request = host.GetRequest(route, HttpMethod.Post);
153+
154+
var args = new List<KeyValuePair<string, string>>()
155+
{
156+
new("user", username), new("password", password)
157+
};
158+
159+
request.Content = new FormUrlEncodedContent(args);
160+
161+
return await host.GetResponseAsync(request);
162+
}
163+
164+
private TestHost GetHost(TestIntegration? integration = null)
165+
{
166+
var auth = WebAuthentication.Simple(integration ?? new());
167+
168+
var content = Layout.Create()
169+
.Add("content", Content.From(Resource.FromString("Hello World")))
170+
.Add(auth);
171+
172+
return TestHost.Run(content);
173+
}
174+
175+
private class TestIntegration : ISimpleWebAuthIntegration
176+
{
177+
private readonly List<MyUser> _Users = new();
178+
179+
private readonly Dictionary<string, MyUser> _Sessions = new();
180+
181+
public TestIntegration AddUser(string username, string password)
182+
{
183+
_Users.Add(new(username, password));
184+
return this;
185+
}
186+
187+
public ValueTask<bool> CheckSetupRequired(IRequest request) => new(_Users.Count == 0);
188+
189+
public ValueTask PerformSetup(IRequest request, string username, string password)
190+
{
191+
_Users.Add(new(username, password));
192+
return new();
193+
}
194+
195+
public ValueTask<IUser?> PerformLogin(IRequest request, string username, string password)
196+
{
197+
return new(_Users.FirstOrDefault(e => e.Name == username && e.Password == password));
198+
}
199+
200+
public ValueTask<string> StartSessionAsync(IRequest request, IUser user)
201+
{
202+
var token = Guid.NewGuid().ToString();
203+
_Sessions.Add(token, (MyUser)user);
204+
return new(token);
205+
}
206+
207+
public ValueTask<IUser?> VerifyTokenAsync(string sessionToken)
208+
{
209+
if (_Sessions.TryGetValue(sessionToken, out var user))
210+
{
211+
return new(user);
212+
}
213+
214+
return new();
215+
}
216+
217+
}
218+
219+
public class MyUser : IUser
220+
{
221+
222+
public string Name { get; }
223+
224+
public string Password { get; }
225+
226+
public string DisplayName => Name;
227+
228+
public MyUser(string name, string password) { Name = name; Password = password; }
229+
230+
}
231+
232+
#endregion
233+
234+
}
235+
236+
}

0 commit comments

Comments
 (0)