@@ -257,6 +257,119 @@ public async Task GetAllSymbolsAsync_WhenHttpClientThrows_CapturesExceptionMessa
257257 handler . VerifyAll ( ) ;
258258 }
259259
260+ [ Test ]
261+ public async Task GetMarketStatusAsync_WhenResponseIsSuccessful_RequestsMarketStatusEndpointAndMapsResponse ( )
262+ {
263+ var mockHttp = new MockHttpMessageHandler ( ) ;
264+ mockHttp . Expect ( HttpMethod . Get , $ "{ BaseUrl } /stock/market-status?exchange=US&token={ ApiKey } ")
265+ . Respond ( "application/json" , """
266+ {
267+ "exchange": "US",
268+ "holiday": "",
269+ "isOpen": true,
270+ "session": "regular",
271+ "state": "open",
272+ "timezone": "America/New_York",
273+ "sessionOpen": "2026-05-06 09:30:00",
274+ "sessionClose": "2026-05-06 16:00:00",
275+ "t": 1778088600
276+ }
277+ """ ) ;
278+ var client = CreateClient ( mockHttp ) ;
279+
280+ var result = await client . GetMarketStatusAsync ( "US" ) ;
281+
282+ result . ResponseCode . ShouldBe ( ( int ) HttpStatusCode . OK ) ;
283+ result . ErrorMessage . ShouldBeNull ( ) ;
284+ result . MarketStatus . ShouldNotBeNull ( ) ;
285+ result . MarketStatus . Exchange . ShouldBe ( "US" ) ;
286+ result . MarketStatus . Holiday . ShouldBe ( "" ) ;
287+ result . MarketStatus . IsOpen . ShouldBeTrue ( ) ;
288+ result . MarketStatus . Session . ShouldBe ( "regular" ) ;
289+ result . MarketStatus . State . ShouldBe ( "open" ) ;
290+ result . MarketStatus . Timezone . ShouldBe ( "America/New_York" ) ;
291+ result . MarketStatus . SessionOpen . ShouldBe ( "2026-05-06 09:30:00" ) ;
292+ result . MarketStatus . SessionClose . ShouldBe ( "2026-05-06 16:00:00" ) ;
293+ result . MarketStatus . Timestamp . ShouldBe ( 1778088600 ) ;
294+ mockHttp . VerifyNoOutstandingExpectation ( ) ;
295+ }
296+
297+ [ Test ]
298+ public async Task GetMarketStatusAsync_WhenResponseIsUnsuccessful_SetsStatusCodeAndRawErrorMessage ( )
299+ {
300+ const string errorBody = """{"error":"Exchange not found"}""" ;
301+ var mockHttp = new MockHttpMessageHandler ( ) ;
302+ mockHttp . Expect ( HttpMethod . Get , $ "{ BaseUrl } /stock/market-status?exchange=NOPE&token={ ApiKey } ")
303+ . Respond ( HttpStatusCode . BadRequest , "application/json" , errorBody ) ;
304+ var client = CreateClient ( mockHttp ) ;
305+
306+ var result = await client . GetMarketStatusAsync ( "NOPE" ) ;
307+
308+ result . ResponseCode . ShouldBe ( ( int ) HttpStatusCode . BadRequest ) ;
309+ result . ErrorMessage . ShouldBe ( errorBody ) ;
310+ result . MarketStatus . ShouldBeNull ( ) ;
311+ mockHttp . VerifyNoOutstandingExpectation ( ) ;
312+ }
313+
314+ [ Test ]
315+ public async Task GetMarketHolidaysAsync_WhenResponseIsSuccessful_RequestsMarketHolidayEndpointAndMapsResponse ( )
316+ {
317+ var mockHttp = new MockHttpMessageHandler ( ) ;
318+ mockHttp . Expect ( HttpMethod . Get , $ "{ BaseUrl } /stock/market-holiday?exchange=US&token={ ApiKey } ")
319+ . Respond ( "application/json" , """
320+ {
321+ "exchange": "US",
322+ "data": [
323+ {
324+ "eventName": "Memorial Day",
325+ "atDate": "2026-05-25",
326+ "tradingHour": ""
327+ },
328+ {
329+ "eventName": "Independence Day",
330+ "atDate": "2026-07-03",
331+ "tradingHour": "09:30-13:00"
332+ }
333+ ],
334+ "timezone": "America/New_York"
335+ }
336+ """ ) ;
337+ var client = CreateClient ( mockHttp ) ;
338+
339+ var result = await client . GetMarketHolidaysAsync ( "US" ) ;
340+
341+ result . ResponseCode . ShouldBe ( ( int ) HttpStatusCode . OK ) ;
342+ result . ErrorMessage . ShouldBeNull ( ) ;
343+ result . MarketHoliday . ShouldNotBeNull ( ) ;
344+ result . MarketHoliday . Exchange . ShouldBe ( "US" ) ;
345+ result . MarketHoliday . Timezone . ShouldBe ( "America/New_York" ) ;
346+ result . MarketHoliday . Data . Count . ShouldBe ( 2 ) ;
347+ result . MarketHoliday . Data [ 0 ] . EventName . ShouldBe ( "Memorial Day" ) ;
348+ result . MarketHoliday . Data [ 0 ] . AtDate . ShouldBe ( "2026-05-25" ) ;
349+ result . MarketHoliday . Data [ 0 ] . TradingHour . ShouldBe ( "" ) ;
350+ result . MarketHoliday . Data [ 1 ] . EventName . ShouldBe ( "Independence Day" ) ;
351+ result . MarketHoliday . Data [ 1 ] . AtDate . ShouldBe ( "2026-07-03" ) ;
352+ result . MarketHoliday . Data [ 1 ] . TradingHour . ShouldBe ( "09:30-13:00" ) ;
353+ mockHttp . VerifyNoOutstandingExpectation ( ) ;
354+ }
355+
356+ [ Test ]
357+ public async Task GetMarketHolidaysAsync_WhenResponseIsUnsuccessful_SetsStatusCodeAndRawErrorMessage ( )
358+ {
359+ const string errorBody = """{"error":"Exchange not found"}""" ;
360+ var mockHttp = new MockHttpMessageHandler ( ) ;
361+ mockHttp . Expect ( HttpMethod . Get , $ "{ BaseUrl } /stock/market-holiday?exchange=NOPE&token={ ApiKey } ")
362+ . Respond ( HttpStatusCode . BadRequest , "application/json" , errorBody ) ;
363+ var client = CreateClient ( mockHttp ) ;
364+
365+ var result = await client . GetMarketHolidaysAsync ( "NOPE" ) ;
366+
367+ result . ResponseCode . ShouldBe ( ( int ) HttpStatusCode . BadRequest ) ;
368+ result . ErrorMessage . ShouldBe ( errorBody ) ;
369+ result . MarketHoliday . ShouldBeNull ( ) ;
370+ mockHttp . VerifyNoOutstandingExpectation ( ) ;
371+ }
372+
260373 private static FinnHubClient CreateClient ( HttpMessageHandler handler ) =>
261374 new ( new HttpClient ( handler ) , new FinnHubSharpConfiguration
262375 {
0 commit comments