Loading StockMonitor.Tests/FacadeTests/TestFacade.cs +4 −4 Original line number Diff line number Diff line Loading @@ -70,13 +70,13 @@ public class TestFacade public TestFacade WithHttpServiceSuccess() { _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>())).ReturnsAsync(""); _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(""); return this; } public TestFacade WithHttpServiceThrowsArkCsvScrapeException() { _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>())).ThrowsAsync(new ArkCsvScrapeException()); _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>())).ThrowsAsync(new ArkCsvScrapeException()); return this; } Loading Loading @@ -199,13 +199,13 @@ public class TestFacade public TestFacade VerifyHttpServiceCalled() { _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>()), Times.Once); _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once); return this; } public TestFacade VerifyHttpServiceNotCalled() { _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>()), Times.Never); _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never); return this; } Loading StockMonitor.Tests/ServiceTests/HttpServiceTests.cs +5 −3 Original line number Diff line number Diff line Loading @@ -27,13 +27,15 @@ public class HttpServiceTests using (var scope = serviceProvider.CreateScope()) { var httpService = scope.ServiceProvider.GetRequiredService<IHttpService>(); var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(30)); Assert.Multiple(() => { var ex = Assert.ThrowsAsync<ArkCsvScrapeException>(async () => await httpService.ScrapeCsv(inputString)); var ex = Assert.ThrowsAsync<ArkCsvNotFoundException>(async () => await httpService.ScrapeCsv(inputString, cancellationTokenSource.Token)); Assert.IsNotNull(ex); Assert.IsInstanceOf(typeof(ArkCsvScrapeException), ex); Assert.IsInstanceOf(typeof(ArkCsvNotFoundException), ex); Assert.True( ex?.Message.StartsWith("Failed to scrape CSV from URL:", StringComparison.InvariantCulture)); ex?.Message.StartsWith("CSV data not found at URL:", StringComparison.InvariantCulture)); }); } } Loading StockMonitor/Configuration/EmailConfiguration.cs +6 −6 Original line number Diff line number Diff line Loading @@ -2,15 +2,15 @@ { public class EmailConfiguration { public string Email { get; set; } = ""; public string Password { get; set; } = ""; public string Email { get; set; } = "stockmonitor.report.pv.psq@outlook.com"; public string Password { get; set; } = "ja6UydhVcev63Ft"; public string SmtpClient { get; set; } = ""; public string SmtpClient { get; set; } = "smtp.office365.com"; public int SmtpPort { get; set; } public int SmtpPort { get; set; } = 587; public bool UseSsl { get; set; } public bool UseSsl { get; set; } = true; public string ReportName { get; set; } = ""; public string ReportName { get; set; } = "report.csv"; } } StockMonitor/Configuration/StockConfiguration.cs +3 −2 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ { public class StockConfiguration { public string StocksFile { get; set; } = ""; public string StocksFile { get; set; } = "stocks.json"; public string CsvUrl { get; set; } = ""; public string CsvUrl { get; set; } = "https://ark-funds.com/wp-content/uploads/funds-etf-csv/ARK_INNOVATION_ETF_ARKK_HOLDINGS.csv"; public int RequestTimeout { get; set; } = 30; } } StockMonitor/Exceptions/ArkCsvForbiddenException.cs 0 → 100644 +18 −0 Original line number Diff line number Diff line namespace StockMonitor.Exceptions; public class ArkCsvForbiddenException : Exception { public ArkCsvForbiddenException() { } public ArkCsvForbiddenException(string message) : base(message) { } public ArkCsvForbiddenException(string message, Exception inner) : base(message, inner) { } } Loading
StockMonitor.Tests/FacadeTests/TestFacade.cs +4 −4 Original line number Diff line number Diff line Loading @@ -70,13 +70,13 @@ public class TestFacade public TestFacade WithHttpServiceSuccess() { _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>())).ReturnsAsync(""); _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(""); return this; } public TestFacade WithHttpServiceThrowsArkCsvScrapeException() { _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>())).ThrowsAsync(new ArkCsvScrapeException()); _httpServiceMock.Setup(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>())).ThrowsAsync(new ArkCsvScrapeException()); return this; } Loading Loading @@ -199,13 +199,13 @@ public class TestFacade public TestFacade VerifyHttpServiceCalled() { _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>()), Times.Once); _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once); return this; } public TestFacade VerifyHttpServiceNotCalled() { _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>()), Times.Never); _httpServiceMock.Verify(mock => mock.ScrapeCsv(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never); return this; } Loading
StockMonitor.Tests/ServiceTests/HttpServiceTests.cs +5 −3 Original line number Diff line number Diff line Loading @@ -27,13 +27,15 @@ public class HttpServiceTests using (var scope = serviceProvider.CreateScope()) { var httpService = scope.ServiceProvider.GetRequiredService<IHttpService>(); var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(30)); Assert.Multiple(() => { var ex = Assert.ThrowsAsync<ArkCsvScrapeException>(async () => await httpService.ScrapeCsv(inputString)); var ex = Assert.ThrowsAsync<ArkCsvNotFoundException>(async () => await httpService.ScrapeCsv(inputString, cancellationTokenSource.Token)); Assert.IsNotNull(ex); Assert.IsInstanceOf(typeof(ArkCsvScrapeException), ex); Assert.IsInstanceOf(typeof(ArkCsvNotFoundException), ex); Assert.True( ex?.Message.StartsWith("Failed to scrape CSV from URL:", StringComparison.InvariantCulture)); ex?.Message.StartsWith("CSV data not found at URL:", StringComparison.InvariantCulture)); }); } } Loading
StockMonitor/Configuration/EmailConfiguration.cs +6 −6 Original line number Diff line number Diff line Loading @@ -2,15 +2,15 @@ { public class EmailConfiguration { public string Email { get; set; } = ""; public string Password { get; set; } = ""; public string Email { get; set; } = "stockmonitor.report.pv.psq@outlook.com"; public string Password { get; set; } = "ja6UydhVcev63Ft"; public string SmtpClient { get; set; } = ""; public string SmtpClient { get; set; } = "smtp.office365.com"; public int SmtpPort { get; set; } public int SmtpPort { get; set; } = 587; public bool UseSsl { get; set; } public bool UseSsl { get; set; } = true; public string ReportName { get; set; } = ""; public string ReportName { get; set; } = "report.csv"; } }
StockMonitor/Configuration/StockConfiguration.cs +3 −2 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ { public class StockConfiguration { public string StocksFile { get; set; } = ""; public string StocksFile { get; set; } = "stocks.json"; public string CsvUrl { get; set; } = ""; public string CsvUrl { get; set; } = "https://ark-funds.com/wp-content/uploads/funds-etf-csv/ARK_INNOVATION_ETF_ARKK_HOLDINGS.csv"; public int RequestTimeout { get; set; } = 30; } }
StockMonitor/Exceptions/ArkCsvForbiddenException.cs 0 → 100644 +18 −0 Original line number Diff line number Diff line namespace StockMonitor.Exceptions; public class ArkCsvForbiddenException : Exception { public ArkCsvForbiddenException() { } public ArkCsvForbiddenException(string message) : base(message) { } public ArkCsvForbiddenException(string message, Exception inner) : base(message, inner) { } }