11namespace SqlStreamStore . HAL . Tests
22{
3+ using System ;
4+ using System . Collections ;
5+ using System . Collections . Generic ;
6+ using System . Linq ;
7+ using System . Net ;
8+ using System . Net . Http ;
9+ using System . Net . Http . Headers ;
10+ using System . Threading . Tasks ;
11+ using Newtonsoft . Json . Linq ;
12+ using Shouldly ;
13+ using SqlStreamStore . Streams ;
14+ using Xunit ;
15+
316 public class StreamMetadataTests
417 {
18+ private const string StreamId = "a-stream" ;
19+
520 private readonly SqlStreamStoreHalMiddlewareFixture _fixture ;
621
722 public StreamMetadataTests ( )
823 {
924 _fixture = new SqlStreamStoreHalMiddlewareFixture ( ) ;
1025 }
26+
27+ [ Fact ]
28+ public async Task get_metadata_when_metadata_stream_does_not_exist ( )
29+ {
30+ using ( var response =
31+ await _fixture . HttpClient . SendAsync (
32+ new HttpRequestMessage ( HttpMethod . Get , $ "/streams/{ StreamId } /metadata") ) )
33+ {
34+ response . StatusCode . ShouldBe ( HttpStatusCode . NotFound ) ;
35+
36+ var resource = await response . AsHal ( ) ;
37+
38+ ( ( string ) resource . State . streamId ) . ShouldBe ( StreamId ) ;
39+ ( ( int ) resource . State . metadataStreamVersion ) . ShouldBe ( ExpectedVersion . NoStream ) ;
40+ ( ( int ? ) resource . State . maxAge ) . ShouldBe ( default ( int ? ) ) ;
41+ ( ( int ? ) resource . State . maxCount ) . ShouldBe ( default ( int ? ) ) ;
42+ ( ( string ) resource . State . metaJson ) . ShouldBeNull ( ) ;
43+
44+ resource . ShouldLink ( Constants . Relations . Self , "metadata" ) ;
45+ resource . ShouldLink ( Constants . Relations . Feed , "../" ) ;
46+ }
47+ }
48+
49+ [ Fact ]
50+ public async Task get_metadata_when_metadata_stream_does_exist ( )
51+ {
52+ using ( await _fixture . HttpClient . SendAsync (
53+ new HttpRequestMessage ( HttpMethod . Post , $ "/streams/{ StreamId } /metadata")
54+ {
55+ Content = new StringContent ( JObject . FromObject ( new
56+ {
57+ maxAge = 30 ,
58+ maxCount = 20 ,
59+ metaJson = new
60+ {
61+ type = "a-type"
62+ }
63+ } ) . ToString ( ) )
64+ {
65+ Headers =
66+ {
67+ ContentType = new MediaTypeHeaderValue ( "application/json" )
68+ }
69+ }
70+ } ) )
71+ using ( var response =
72+ await _fixture . HttpClient . SendAsync (
73+ new HttpRequestMessage ( HttpMethod . Get , $ "/streams/{ StreamId } /metadata") ) )
74+ {
75+ response . StatusCode . ShouldBe ( HttpStatusCode . OK ) ;
76+
77+ var resource = await response . AsHal ( ) ;
78+
79+ ( ( string ) resource . State . streamId ) . ShouldBe ( StreamId ) ;
80+ ( ( int ) resource . State . metadataStreamVersion ) . ShouldBe ( 0 ) ;
81+ ( ( int ? ) resource . State . maxAge ) . ShouldBe ( 30 ) ;
82+ ( ( int ? ) resource . State . maxCount ) . ShouldBe ( 20 ) ;
83+ JToken . DeepEquals ( JObject . Parse ( ( string ) resource . State . metaJson ) ,
84+ JObject . FromObject ( new
85+ {
86+ type = "a-type"
87+ } ) ) . ShouldBeTrue ( ) ;
88+
89+ resource . ShouldLink ( Constants . Relations . Self , "metadata" ) ;
90+ resource . ShouldLink ( Constants . Relations . Feed , "../" ) ;
91+ }
92+ }
93+
94+ [ Fact ]
95+ public async Task set_metadata ( )
96+ {
97+ using ( var response = await _fixture . HttpClient . SendAsync (
98+ new HttpRequestMessage ( HttpMethod . Post , $ "/streams/{ StreamId } /metadata")
99+ {
100+ Content = new StringContent ( JObject . FromObject ( new
101+ {
102+ maxAge = 30 ,
103+ maxCount = 20 ,
104+ metaJson = new
105+ {
106+ type = "a-type"
107+ }
108+ } ) . ToString ( ) )
109+ {
110+ Headers =
111+ {
112+ ContentType = new MediaTypeHeaderValue ( "application/json" )
113+ }
114+ }
115+ } ) )
116+ {
117+ response . StatusCode . ShouldBe ( HttpStatusCode . OK ) ;
118+
119+ var resource = await response . AsHal ( ) ;
120+
121+ ( ( string ) resource . State . streamId ) . ShouldBe ( StreamId ) ;
122+ ( ( int ? ) resource . State . maxAge ) . ShouldBe ( 30 ) ;
123+ ( ( int ? ) resource . State . maxCount ) . ShouldBe ( 20 ) ;
124+ JToken . DeepEquals ( JObject . Parse ( ( string ) resource . State . metaJson ) ,
125+ JObject . FromObject ( new
126+ {
127+ type = "a-type"
128+ } ) ) . ShouldBeTrue ( ) ;
129+
130+ resource . ShouldLink ( Constants . Relations . Self , "metadata" ) ;
131+ resource . ShouldLink ( Constants . Relations . Feed , "../" ) ;
132+ }
133+ }
134+
135+ private static IEnumerable < int [ ] > WrongExpectedVersions ( )
136+ {
137+ yield return new [ ] { ExpectedVersion . NoStream , ExpectedVersion . NoStream } ;
138+ yield return new [ ] { ExpectedVersion . NoStream , 2 } ;
139+ }
140+
141+ public static IEnumerable < object [ ] > WrongExpectedVersionCases ( )
142+ => WrongExpectedVersions ( ) . Select ( s => new object [ ] { s } ) ;
143+
144+ [ Theory ]
145+ [ MemberData ( nameof ( WrongExpectedVersionCases ) ) ]
146+ public async Task set_wrong_expected_version ( int [ ] expectedVersions )
147+ {
148+ for ( var i = 0 ; i < expectedVersions . Length - 1 ; i ++ )
149+ {
150+ using ( await _fixture . HttpClient . SendAsync (
151+ new HttpRequestMessage ( HttpMethod . Post , $ "/streams/{ StreamId } /metadata")
152+ {
153+ Headers =
154+ {
155+ { Constants . Headers . ExpectedVersion , $ "{ expectedVersions [ i ] } " }
156+ } ,
157+ Content = new StringContent ( JObject . FromObject ( new
158+ {
159+ maxAge = 30 ,
160+ maxCount = 20 ,
161+ metaJson = new
162+ {
163+ type = "a-type"
164+ }
165+ } ) . ToString ( ) )
166+ {
167+ Headers =
168+ {
169+ ContentType = new MediaTypeHeaderValue ( "application/json" )
170+ }
171+ }
172+ } ) )
173+ { }
174+ }
175+
176+ using ( var response = await _fixture . HttpClient . SendAsync (
177+ new HttpRequestMessage ( HttpMethod . Post , $ "/streams/{ StreamId } /metadata")
178+ {
179+ Headers =
180+ {
181+ { Constants . Headers . ExpectedVersion , $ "{ expectedVersions [ expectedVersions . Length - 1 ] } " }
182+ } ,
183+ Content = new StringContent ( JObject . FromObject ( new
184+ {
185+ maxAge = 30 ,
186+ maxCount = 20 ,
187+ metaJson = new
188+ {
189+ type = "a-type"
190+ }
191+ } ) . ToString ( ) )
192+ {
193+ Headers =
194+ {
195+ ContentType = new MediaTypeHeaderValue ( "application/json" )
196+ }
197+ }
198+ } ) )
199+ {
200+ response . StatusCode . ShouldBe ( HttpStatusCode . Conflict ) ;
201+ response . Content . Headers . ContentType . ShouldBe ( new MediaTypeHeaderValue (
202+ Constants . Headers . ContentTypes . HalJson ) ) ;
203+ }
204+
205+ var page = await _fixture . StreamStore . ReadStreamForwards ( $ "$${ StreamId } ", 0 , int . MaxValue ) ;
206+
207+ page . Status . ShouldBe ( PageReadStatus . Success ) ;
208+ page . Messages . Length . ShouldBe ( expectedVersions . Length - 1 ) ;
209+ }
11210 }
12211}
0 commit comments