1
+ using System . Net ;
2
+ using System . Reflection ;
3
+ using System . Text . Json ;
4
+ using TempMail . Client . Requests ;
5
+ using TempMail . Client . Responses ;
6
+
7
+ namespace TempMail . Client . Tests ;
8
+
9
+ internal class MockingHttpMessageHandler : HttpMessageHandler
10
+ {
11
+ private bool _returnErrors ;
12
+
13
+ private static MockingHttpMessageHandler ? _instance ;
14
+
15
+ public MockingHttpMessageHandler ( )
16
+ {
17
+ if ( _instance != null )
18
+ {
19
+ throw new InvalidOperationException ( "MockingHttpMessageHandler instance already exists" ) ;
20
+ }
21
+
22
+ _instance = this ;
23
+ }
24
+
25
+
26
+ private static readonly IReadOnlyCollection < ( HandlerAttribute Handler , Func < HttpRequestMessage , Task < HttpResponseMessage > > Method ) >
27
+ Handlers =
28
+ typeof ( MockingHttpMessageHandler )
29
+ . GetMethods ( BindingFlags . Instance | BindingFlags . NonPublic )
30
+ . Select ( x =>
31
+ ( x . GetCustomAttribute < HandlerAttribute > ( ) ! , CreateMethod ( x ) ) )
32
+ . Where ( x => x . Item1 != null )
33
+ . ToList ( ) ;
34
+
35
+ protected override Task < HttpResponseMessage > SendAsync ( HttpRequestMessage request , CancellationToken cancellationToken )
36
+ {
37
+ foreach ( var handler in Handlers )
38
+ {
39
+ if ( handler . Handler . Matches ( request ) == null )
40
+ {
41
+ continue ;
42
+ }
43
+
44
+ return handler . Method ( request ) ;
45
+ }
46
+
47
+ throw new Exception ( $ "No handler found for { request . RequestUri } ") ;
48
+ }
49
+
50
+ private HttpResponseMessage ReturnError < TResponse > ( )
51
+ {
52
+ var httpResponseMessage = new HttpResponseMessage ( HttpStatusCode . BadRequest ) ;
53
+
54
+ httpResponseMessage . Content = new StringContent ( JsonSerializer . Serialize (
55
+ new ErrorResponse (
56
+ new Error ( ErrorType . ApiError , "api_error" , "An error occured during request handling" ) ,
57
+ new ErrorMeta ( Guid . NewGuid ( ) . ToString ( ) ) ) ,
58
+ JsonOptions ) ) ;
59
+
60
+ return httpResponseMessage ;
61
+ }
62
+
63
+ [ Handler ( ".*/v1/emails" , "POST" ) ]
64
+ private async Task < HttpResponseMessage > HandleCreateEmail ( HttpRequestMessage request )
65
+ {
66
+ if ( _returnErrors )
67
+ {
68
+ return ReturnError < HttpResponseMessage > ( ) ;
69
+ }
70
+ var requestBody = JsonSerializer . Deserialize < CreateEmailRequest > (
71
+ await request . Content . ReadAsStringAsync ( ) ,
72
+ JsonOptions ) ;
73
+
74
+ var httpResponseMessage = new HttpResponseMessage ( HttpStatusCode . OK ) ;
75
+ var resp = requestBody switch
76
+ {
77
+ CreateEmailByEmailRequest { Email : var email } => new CreateEmailResponse ( email , int . MaxValue ) ,
78
+ CreateEmailByDomainRequest { Domain : var domain } => new CreateEmailResponse ( $ "random@{ domain } ", int . MaxValue ) ,
79
+ CreateEmailByDomainTypeRequest { DomainType : var domainType } => new CreateEmailResponse ( $ "random@{ domainType . ToString ( ) . ToLowerInvariant ( ) } .io", int . MaxValue ) ,
80
+ _ => throw new Exception ( $ "Unknown request body type: { requestBody ? . GetType ( ) . FullName } ")
81
+ } ;
82
+ httpResponseMessage . Content = new StringContent ( JsonSerializer . Serialize ( resp , new JsonSerializerOptions
83
+ {
84
+ PropertyNamingPolicy = JsonNamingPolicy . SnakeCaseLower ,
85
+ Converters = { new CreateEmailRequestJsonConverter ( ) }
86
+ } ) ) ;
87
+ return httpResponseMessage ;
88
+ }
89
+
90
+ private static JsonSerializerOptions JsonOptions =>
91
+ new ( )
92
+ {
93
+ PropertyNamingPolicy = JsonNamingPolicy . SnakeCaseLower ,
94
+ Converters = { new CreateEmailRequestJsonConverter ( ) }
95
+ } ;
96
+
97
+ private static Func < HttpRequestMessage , Task < HttpResponseMessage > > CreateMethod ( MethodInfo methodInfo ) => request =>
98
+ {
99
+ var handler = methodInfo . GetCustomAttribute < HandlerAttribute > ( ) ! ;
100
+ var match = handler . Matches ( request ) ! ;
101
+
102
+ if ( match == string . Empty )
103
+ {
104
+ return ( Task < HttpResponseMessage > ) methodInfo . Invoke ( _instance , [ request ] ) ! ;
105
+ }
106
+
107
+ return ( Task < HttpResponseMessage > ) methodInfo . Invoke ( _instance , [ request , match ] ) ! ;
108
+ } ;
109
+
110
+ public void ReturnErrors ( bool returnErrors = true ) => _returnErrors = returnErrors ;
111
+
112
+ public new void Dispose ( )
113
+ {
114
+ _instance = null ! ;
115
+ base . Dispose ( ) ;
116
+ }
117
+ }
0 commit comments