Skip to content

Commit c4e208d

Browse files
committed
add validation tests
Signed-off-by: Kevin <kevin.dinh@lissi.id>
1 parent 17c4599 commit c4e208d

File tree

5 files changed

+320
-6
lines changed

5 files changed

+320
-6
lines changed

global.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
{
2-
"sdk": {
3-
"version": "6.0.0",
4-
"rollForward": "latestFeature"
5-
}
6-
}
1+
{
2+
"sdk": {
3+
"version": "8.0.0",
4+
"rollForward": "latestFeature"
5+
}
6+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using FluentAssertions;
2+
using WalletFramework.Core.Functional;
3+
using Xunit;
4+
5+
namespace WalletFramework.Core.Tests.Validation;
6+
7+
public class ApplyTests
8+
{
9+
private record Sample(int X1, int X2, int X3, int X4, int X5, int X6, int X7)
10+
{
11+
public int Sum() => X1 + X2 + X3 + X4 + X5 + X6 + X7;
12+
}
13+
14+
private static Sample CreateSample(int x1, int x2, int x3, int x4, int x5, int x6, int x7) =>
15+
new(x1, x2, x3, x4, x5, x6, x7);
16+
17+
[Fact]
18+
public void ApplyWorks()
19+
{
20+
const int expected = 1 + 2 + 3 + 4 + 5 + 6 + 7;
21+
var func = ValidationFun.Valid(CreateSample);
22+
23+
var sut = func
24+
.Apply(1)
25+
.Apply(2)
26+
.Apply(3)
27+
.Apply(4)
28+
.Apply(5)
29+
.Apply(6)
30+
.Apply(7);
31+
32+
sut.UnwrapOrThrow().Sum().Should().Be(expected);
33+
}
34+
}
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
using FluentAssertions;
2+
using LanguageExt;
3+
using WalletFramework.Core.Functional;
4+
using WalletFramework.Core.Functional.Errors;
5+
using Xunit;
6+
7+
namespace WalletFramework.Core.Tests.Validation;
8+
9+
public class ValidationTests
10+
{
11+
[Fact]
12+
public void AggregationWorks()
13+
{
14+
Validator<int> greaterThanZero = i => i > 0
15+
? ValidationFun.Valid(i)
16+
: new SampleError();
17+
18+
Validator<int> isEven = i => i % 2 == 0
19+
? ValidationFun.Valid(i)
20+
: new SampleError();
21+
22+
var sut = new List<Validator<int>> { greaterThanZero, isEven }.AggregateValidators();
23+
24+
var one = sut(1);
25+
var two = sut(2);
26+
27+
one.IsSuccess.Should().BeFalse();
28+
two.IsSuccess.Should().BeTrue();
29+
}
30+
31+
[Fact]
32+
public void FallbackWorks()
33+
{
34+
var one = new SampleError().ToInvalid<Validation<int>>();
35+
36+
var sut = one.Fallback(2);
37+
38+
sut.UnwrapOrThrow().Should().Be(2);
39+
}
40+
41+
[Fact]
42+
public void FirstValidWorks()
43+
{
44+
const string one = "1";
45+
const string nan = "NaN";
46+
Validator<string, int> valid = str =>
47+
{
48+
try
49+
{
50+
return ValidationFun.Valid(int.Parse(str));
51+
}
52+
catch (Exception )
53+
{
54+
return new SampleError();
55+
}
56+
};
57+
Validator<string, int> invalid = _ => new SampleError();
58+
59+
var sut = new List<Validator<string, int>> { invalid, valid }.FirstValid();
60+
61+
var oneValid = sut(one);
62+
var nanInvalid = sut(nan);
63+
64+
oneValid.UnwrapOrThrow().Should().Be(1);
65+
nanInvalid.Match(
66+
i => Assert.Fail("Validation must fail"),
67+
errors =>
68+
{
69+
errors.Should().AllBeOfType<NoItemsSucceededValidationError<int>>();
70+
errors.Should().ContainSingle();
71+
}
72+
);
73+
}
74+
75+
[Theory]
76+
[InlineData(true)]
77+
[InlineData(false)]
78+
public void MatchWorks(bool valid)
79+
{
80+
Validation<int> validation = valid
81+
? 1
82+
: new SampleError();
83+
84+
validation.Match(
85+
_ => valid.Should().BeTrue(),
86+
errors =>
87+
{
88+
valid.Should().BeFalse();
89+
errors.Should().AllBeOfType<SampleError>();
90+
errors.Should().ContainSingle();
91+
});
92+
}
93+
94+
[Fact]
95+
public void OnSuccessWorks()
96+
{
97+
var one = ValidationFun.Valid("1");
98+
99+
var sut = one.OnSuccess(int.Parse);
100+
101+
sut.UnwrapOrThrow().Should().Be(1);
102+
}
103+
104+
[Fact]
105+
public async Task OnSuccessAsyncWorks()
106+
{
107+
var one = ValidationFun.Valid("1").AsTask();
108+
109+
var sut = await one.OnSuccess(int.Parse);
110+
111+
sut.UnwrapOrThrow().Should().Be(1);
112+
}
113+
114+
[Fact]
115+
public void SelectManyWorks()
116+
{
117+
var one = ValidationFun.Valid("1");
118+
119+
var sut = one.SelectMany(
120+
_ => ValidationFun.Valid(1),
121+
(e1, e2) => int.Parse(e1) + e2
122+
);
123+
124+
sut.UnwrapOrThrow().Should().Be(2);
125+
}
126+
127+
[Fact]
128+
public void SelectWorks()
129+
{
130+
var one = ValidationFun.Valid("1");
131+
132+
var sut = one.Select(int.Parse);
133+
134+
sut.Match(
135+
i => i.Should().Be(1),
136+
_ => Assert.Fail("Validation must not fail"));
137+
}
138+
139+
[Fact]
140+
public void TraverseAllWorks()
141+
{
142+
var validStrs = new List<string>
143+
{
144+
"1",
145+
"2",
146+
"3"
147+
};
148+
149+
var invalidStrs = new List<string>
150+
{
151+
"1",
152+
"2",
153+
"Three"
154+
};
155+
156+
var sutValid = validStrs.TraverseAll(s =>
157+
{
158+
try
159+
{
160+
return ValidationFun.Valid(int.Parse(s));
161+
}
162+
catch (Exception)
163+
{
164+
return new SampleError();
165+
}
166+
});
167+
168+
var sutInvalid = invalidStrs.TraverseAll(str =>
169+
{
170+
try
171+
{
172+
return ValidationFun.Valid(int.Parse(str));
173+
}
174+
catch (Exception)
175+
{
176+
return new SampleError();
177+
}
178+
});
179+
180+
sutValid.IsSuccess.Should().BeTrue();
181+
sutInvalid.IsSuccess.Should().BeFalse();
182+
}
183+
184+
[Fact]
185+
public void TraverseAnyWorks()
186+
{
187+
var strs = new List<string>
188+
{
189+
"One",
190+
"2",
191+
"Three"
192+
};
193+
194+
var sut = strs.TraverseAny(str =>
195+
{
196+
try
197+
{
198+
return ValidationFun.Valid(int.Parse(str));
199+
}
200+
catch (Exception)
201+
{
202+
return new SampleError();
203+
}
204+
});
205+
206+
sut.Match(
207+
ints =>
208+
{
209+
var list = ints.ToList();
210+
211+
list.Should().ContainSingle();
212+
list.First().Should().Be(2);
213+
},
214+
errors =>
215+
{
216+
Assert.Fail("Validation must not fail");
217+
errors.Should().ContainSingle();
218+
errors.Should().AllBeOfType<SampleError>();
219+
}
220+
);
221+
}
222+
223+
[Theory]
224+
[InlineData(true)]
225+
[InlineData(false)]
226+
public void UnwrapOrThrowWorks(bool valid)
227+
{
228+
Validation<int> validation = valid
229+
? 1
230+
: new SampleError();
231+
232+
try
233+
{
234+
validation.UnwrapOrThrow();
235+
valid.Should().BeTrue();
236+
}
237+
catch (Exception)
238+
{
239+
valid.Should().BeFalse();
240+
}
241+
}
242+
243+
private record SampleError() : Error("This is sample error for testing");
244+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="FluentAssertions" Version="6.12.0" />
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0"/>
14+
<PackageReference Include="xunit" Version="2.9.0" />
15+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
16+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
17+
<PrivateAssets>all</PrivateAssets>
18+
</PackageReference>
19+
<PackageReference Include="coverlet.collector" Version="3.1.2">
20+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
21+
<PrivateAssets>all</PrivateAssets>
22+
</PackageReference>
23+
</ItemGroup>
24+
25+
<ItemGroup>
26+
<ProjectReference Include="..\WalletFramework.Core\WalletFramework.Core.csproj" />
27+
</ItemGroup>
28+
29+
</Project>

src/WalletFramework.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mdoc", "Mdoc", "{A1DD69B3-D
5353
EndProject
5454
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WalletFramework.Integration.Tests", "..\test\WalletFramework.Integration.Tests\WalletFramework.Integration.Tests\WalletFramework.Integration.Tests.csproj", "{70DB749B-255A-4B71-8B76-BAD6B091DA7C}"
5555
EndProject
56+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WalletFramework.Core.Tests", "WalletFramework.Core.Tests\WalletFramework.Core.Tests.csproj", "{93B3ED00-4158-4F79-9532-D3E940630A8A}"
57+
EndProject
5658
Global
5759
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5860
Debug|Any CPU = Debug|Any CPU
@@ -135,6 +137,10 @@ Global
135137
{70DB749B-255A-4B71-8B76-BAD6B091DA7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
136138
{70DB749B-255A-4B71-8B76-BAD6B091DA7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
137139
{70DB749B-255A-4B71-8B76-BAD6B091DA7C}.Release|Any CPU.Build.0 = Release|Any CPU
140+
{93B3ED00-4158-4F79-9532-D3E940630A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
141+
{93B3ED00-4158-4F79-9532-D3E940630A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
142+
{93B3ED00-4158-4F79-9532-D3E940630A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
143+
{93B3ED00-4158-4F79-9532-D3E940630A8A}.Release|Any CPU.Build.0 = Release|Any CPU
138144
EndGlobalSection
139145
GlobalSection(SolutionProperties) = preSolution
140146
HideSolutionNode = FALSE
@@ -160,6 +166,7 @@ Global
160166
{F6B3A24B-CDA2-4CC1-9F68-380203355099} = {873772C5-60B9-442B-B06E-C279919B963C}
161167
{0EDD27CB-967F-4451-81AE-309E7F534F1C} = {A1DD69B3-DC35-43CF-AE14-D751722F074A}
162168
{70DB749B-255A-4B71-8B76-BAD6B091DA7C} = {02ADBA96-A50C-44F0-A9D9-FA0629AA2DF4}
169+
{93B3ED00-4158-4F79-9532-D3E940630A8A} = {02ADBA96-A50C-44F0-A9D9-FA0629AA2DF4}
163170
EndGlobalSection
164171
GlobalSection(ExtensibilityGlobals) = postSolution
165172
SolutionGuid = {4FFA80F9-ADC6-40DB-BBD1-A522B8A68560}

0 commit comments

Comments
 (0)