public void Return_Valid_CacheKey() { string account = "51671327713"; string expected = $"account_{account}"; string actual = CacheKeyHelper.GetAccountCacheKey(account); Assert.Equal(expected, actual); }
public void ThrowArgumentNullException() { Assert.Throws <ArgumentNullException>(() => CacheKeyHelper.GetAccountCacheKey(null)); }
public void ThrowArgumentException_If_EmptyOrWhiteSpace(string account) { Assert.Throws <ArgumentException>(() => CacheKeyHelper.GetAccountCacheKey(account)); }
public async Task <ElronAccountModel> Handle(ElronAccountQuery request, CancellationToken cancellationToken) { var accountData = await _memoryCache.GetOrCreateAsync(CacheKeyHelper.GetAccountCacheKey(request.Id), async entry => { // cache the account object for 15minutes entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15); var message = new HttpRequestMessage(HttpMethod.Get, $"/Account/Login?cardNumber={request.Id}&ReturnUrl=%2fAccount%2fStatement%3fallTransactions%3dTrue"); var result = await _httpClient.SendAsync(message, cancellationToken); result.EnsureSuccessStatusCode(); var parser = new HtmlParser(); var content = parser.Parse(await result.Content.ReadAsStringAsync()).QuerySelector(".content"); var balanceNode = content.QuerySelector("fieldset input.currency"); if (balanceNode == null) { throw new ScrapeException("Failed to find balance node."); } if (!decimal.TryParse(balanceNode.Attributes["value"].Value.Replace(",", "."), NumberStyles.Number, CultureInfo.InvariantCulture, out decimal balance)) { throw new ScrapeException("Failed to parse balance."); } var account = new ElronAccountModel { Id = request.Id, Balance = balance, LastCheck = DateTime.Now }; var transactionsTableNode = content.QuerySelector("table > tbody"); if (transactionsTableNode == null) { return(account); } var tableRows = transactionsTableNode.QuerySelectorAll("tr"); foreach (var tableRow in tableRows) { var transaction = new ElronAccountModel.Transaction(); var columns = tableRow.QuerySelectorAll("td"); var dateNode = columns[0]; var nameNode = columns[2]; var sumNode = columns[3].QuerySelector("span"); transaction.Date = DateTime.ParseExact(dateNode.TextContent.Trim(), "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture); transaction.Sum = decimal.Parse(sumNode.TextContent.Replace(",", ".").Trim(), NumberStyles.Number, CultureInfo.InvariantCulture); // This needs a better solution transaction.Name = nameNode.TextContent.Trim().Split('\t')[0].Trim(); var ticketNode = columns[1].QuerySelector("a"); if (ticketNode == null) { goto AddTransaction; } string tickerNodeHref = ticketNode.Attributes["href"].Value; var ticketGuid = Guid.Parse(tickerNodeHref.Substring(tickerNodeHref.Length - 36)); var ticket = new ElronAccountModel.Ticket() { Id = ticketGuid, Number = ticketNode.TextContent.Trim(), Url = new Uri(_httpClient.BaseAddress, tickerNodeHref).AbsoluteUri }; transaction.Ticket = ticket; var validityNode = nameNode.QuerySelector("div.validity"); if (validityNode == null) { goto AddTransaction; } string validityString = validityNode.TextContent.Trim().Substring(10); var dateStrings = validityString.Split('-').Select(d => d.Trim()).ToArray(); var validFrom = DateTime.ParseExact(dateStrings[0], "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture); var validTo = DateTime.ParseExact(dateStrings[1], "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture); var periodTicket = new ElronAccountModel.PeriodTicket() { ValidFrom = validFrom, ValidTo = validTo }; transaction.PeriodTicket = periodTicket; AddTransaction: account.Transactions.Add(transaction); } return(account); }); return(SortAccountTransactions(accountData)); }