@@ -1813,4 +1813,146 @@ public function testCandles_automaticConcurrent_csvFormatWithColumns(): void
18131813 $ this ->assertStringNotContainsString (',l, ' , $ csv );
18141814 $ this ->assertStringNotContainsString (',v ' , $ csv );
18151815 }
1816+
1817+ /**
1818+ * Test CSV format with extended=true parameter.
1819+ *
1820+ * This test covers line 621 in Stocks.php where extended=true is set
1821+ * in the arguments for CSV split requests.
1822+ */
1823+ public function testCandles_automaticConcurrent_csvFormatWithExtended (): void
1824+ {
1825+ // Mock response: NOT from real API output (synthetic CSV response for testing)
1826+ $ csvResponse1 = "t,o,h,l,c,v \n1641220200,177.83,179.31,177.71,178.965,3342579 " ;
1827+ $ csvResponse2 = "1672756200,130.28,130.6999,129.44,129.84,3826842 " ;
1828+
1829+ $ this ->setMockResponses ([
1830+ new Response (200 , [], $ csvResponse1 ),
1831+ new Response (200 , [], $ csvResponse2 ),
1832+ ]);
1833+
1834+ $ result = $ this ->client ->stocks ->candles (
1835+ symbol: 'AAPL ' ,
1836+ from: '2022-01-01 ' ,
1837+ to: '2023-12-31 ' ,
1838+ resolution: '5 ' ,
1839+ extended: true ,
1840+ parameters: new Parameters (format: Format::CSV )
1841+ );
1842+
1843+ $ this ->assertInstanceOf (Candles::class, $ result );
1844+ $ csv = $ result ->getCsv ();
1845+ $ this ->assertStringContainsString ('1641220200 ' , $ csv );
1846+ $ this ->assertStringContainsString ('1672756200 ' , $ csv );
1847+ }
1848+
1849+ /**
1850+ * Test CSV format with adjust_splits=false parameter.
1851+ *
1852+ * This test covers line 624 in Stocks.php where adjustsplits is set
1853+ * in the arguments for CSV split requests.
1854+ */
1855+ public function testCandles_automaticConcurrent_csvFormatWithAdjustSplits (): void
1856+ {
1857+ // Mock response: NOT from real API output (synthetic CSV response for testing)
1858+ $ csvResponse1 = "t,o,h,l,c,v \n1641220200,177.83,179.31,177.71,178.965,3342579 " ;
1859+ $ csvResponse2 = "1672756200,130.28,130.6999,129.44,129.84,3826842 " ;
1860+
1861+ $ this ->setMockResponses ([
1862+ new Response (200 , [], $ csvResponse1 ),
1863+ new Response (200 , [], $ csvResponse2 ),
1864+ ]);
1865+
1866+ $ result = $ this ->client ->stocks ->candles (
1867+ symbol: 'AAPL ' ,
1868+ from: '2022-01-01 ' ,
1869+ to: '2023-12-31 ' ,
1870+ resolution: '5 ' ,
1871+ adjust_splits: false ,
1872+ parameters: new Parameters (format: Format::CSV )
1873+ );
1874+
1875+ $ this ->assertInstanceOf (Candles::class, $ result );
1876+ $ csv = $ result ->getCsv ();
1877+ $ this ->assertStringContainsString ('1641220200 ' , $ csv );
1878+ $ this ->assertStringContainsString ('1672756200 ' , $ csv );
1879+ }
1880+
1881+ /**
1882+ * Test CSV format with adjust_dividends=false parameter.
1883+ *
1884+ * This test covers line 627 in Stocks.php where adjustdividends is set
1885+ * in the arguments for CSV split requests.
1886+ */
1887+ public function testCandles_automaticConcurrent_csvFormatWithAdjustDividends (): void
1888+ {
1889+ // Mock response: NOT from real API output (synthetic CSV response for testing)
1890+ $ csvResponse1 = "t,o,h,l,c,v \n1641220200,177.83,179.31,177.71,178.965,3342579 " ;
1891+ $ csvResponse2 = "1672756200,130.28,130.6999,129.44,129.84,3826842 " ;
1892+
1893+ $ this ->setMockResponses ([
1894+ new Response (200 , [], $ csvResponse1 ),
1895+ new Response (200 , [], $ csvResponse2 ),
1896+ ]);
1897+
1898+ $ result = $ this ->client ->stocks ->candles (
1899+ symbol: 'AAPL ' ,
1900+ from: '2022-01-01 ' ,
1901+ to: '2023-12-31 ' ,
1902+ resolution: '5 ' ,
1903+ adjust_dividends: false ,
1904+ parameters: new Parameters (format: Format::CSV )
1905+ );
1906+
1907+ $ this ->assertInstanceOf (Candles::class, $ result );
1908+ $ csv = $ result ->getCsv ();
1909+ $ this ->assertStringContainsString ('1641220200 ' , $ csv );
1910+ $ this ->assertStringContainsString ('1672756200 ' , $ csv );
1911+ }
1912+
1913+ /**
1914+ * Test CSV format when all responses are empty (no data).
1915+ *
1916+ * This test covers lines 703-705 in Stocks.php where an ApiException is thrown
1917+ * when there are no valid responses and no error messages.
1918+ */
1919+ public function testCandles_automaticConcurrent_csvFormatNoData (): void
1920+ {
1921+ // Mock responses that are empty (not JSON errors, just empty)
1922+ $ this ->setMockResponses ([
1923+ new Response (200 , [], '' ),
1924+ new Response (200 , [], '' ),
1925+ ]);
1926+
1927+ $ this ->expectException (\MarketDataApp \Exceptions \ApiException::class);
1928+ $ this ->expectExceptionMessage ('No data available for the requested date range ' );
1929+
1930+ $ this ->client ->stocks ->candles (
1931+ symbol: 'AAPL ' ,
1932+ from: '2022-01-01 ' ,
1933+ to: '2023-12-31 ' ,
1934+ resolution: '5 ' ,
1935+ parameters: new Parameters (format: Format::CSV )
1936+ );
1937+ }
1938+
1939+ /**
1940+ * Test that filename parameter throws exception with parallel CSV requests.
1941+ *
1942+ * This test covers lines 176-180 in UniversalParameters.php where an exception
1943+ * is thrown when filename is used with parallel requests.
1944+ */
1945+ public function testCandles_automaticConcurrent_csvFormatWithFilename_throwsException (): void
1946+ {
1947+ $ this ->expectException (\InvalidArgumentException::class);
1948+ $ this ->expectExceptionMessage ('filename parameter cannot be used with parallel requests ' );
1949+
1950+ $ this ->client ->stocks ->candles (
1951+ symbol: 'AAPL ' ,
1952+ from: '2022-01-01 ' ,
1953+ to: '2023-12-31 ' ,
1954+ resolution: '5 ' ,
1955+ parameters: new Parameters (format: Format::CSV , filename: '/tmp/test.csv ' )
1956+ );
1957+ }
18161958}
0 commit comments