Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🏖 Sunny outlook after this PR ☀ #85

Merged
merged 3 commits into from
Oct 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions Tests/UtilityBeltxUnitTests/WeatherForecastTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Net;
using System.Text.Json;
using UtilityBelt;
using UtilityBelt.Interfaces;
using UtilityBelt.Models;
using UtilityBelt.Utilities;
using Xunit;

namespace UtilityBeltxUnitTests
{
public class WeatherForecastTests
{
private readonly IServiceProvider services;
private readonly IOptions<SecretsModel> options;
private readonly Mock<IWebClient> webClient = new Mock<IWebClient>();

public WeatherForecastTests()
{
this.services = ServiceProviderBuilder.GetServiceProvider(new string[] { "" });
this.options = services.GetRequiredService<IOptions<SecretsModel>>();
}

[Fact]
public void WeatherForecastReturnsForeCast()
{
var mockWeatherRootResult = getWeatherRootObject();
var jsonresult = JsonSerializer.Serialize(mockWeatherRootResult);
this.webClient.Setup(x => x.DownloadString(It.IsAny<string>())).Returns(jsonresult);
var weatherForecastClient = new TestableWeatherForecast(webClient.Object);

weatherForecastClient.Configure(this.options);
weatherForecastClient.Run("atlanta");

this.webClient.Verify(x => x.DownloadString(It.IsAny<string>()), Times.Once);
}

[Fact]
public void WeatherForecastDoesNotThrowsIfNoKey()
{
this.webClient.Setup(x => x.DownloadString(It.IsAny<string>())).Returns("");

var weatherForecastClient = new TestableWeatherForecast(webClient.Object);
//omitting configure so that the API key isn't set
weatherForecastClient.Run();

//webclient shouldn't be called if the key isn't set
this.webClient.Verify(x => x.DownloadString(It.IsAny<string>()), Times.Never);
}

[Fact]
public void WeatherForecastDoesNotThrowsIfNoResult()
{
this.webClient.Setup(x => x.DownloadString(It.IsAny<string>())).Returns("");

var weatherForecastClient = new TestableWeatherForecast(webClient.Object);
weatherForecastClient.Configure(this.options);
weatherForecastClient.Run("atlanta");

//assert...nothing to do, just shouldnt error
}

private WeatherRoot getWeatherRootObject()
{
var mockSyst = new Sys { Country = "Bolivia", Id = 123456, Sunrise = DateTimeOffset.UtcNow.AddHours(-8).ToUnixTimeSeconds(), Sunset = DateTimeOffset.UtcNow.AddHours(4).ToUnixTimeSeconds() };
var mockMain = new Main { Pressure = 40, FeelsLike = 27, Humidity = 33, Temperature = 24, TempMax = 29, TempMin = 22 };
var mockWind = new Wind { Degrees = 231, Speed = 22 };
var mockWeatherRoot = new WeatherRoot
{
Main = mockMain,
Sys = mockSyst,
Wind = mockWind
};

return mockWeatherRoot;
}

private class TestableWeatherForecast : WeatherForecastUtility
{
public IWebClient webClient { get; set; }

public TestableWeatherForecast(IWebClient webClient) : base()
{
this.webClient = webClient;
}

protected override IWebClient GetWebClient() => this.webClient;
}
}
}
84 changes: 51 additions & 33 deletions Utilities/WeatherForecast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,79 @@
using System.Composition;
using System.Net;
using System.Text.Json;
using UtilityBelt.Interfaces;
using UtilityBelt.Models;

namespace UtilityBelt.Utilities
{
[Export(typeof(IUtility))]
internal class WeatherForecastUtility : IUtility
public class WeatherForecastUtility : IUtility
{
public IList<string> Commands => new List<string> { "weather", "weather forecast"};
public IList<string> Commands => new List<string> { "weather", "weather forecast" };

public string Name => "Weather forecast";

private string _openWeatherMapKey;

public void Configure(IOptions<SecretsModel> options)
{
_openWeatherMapKey = options.Value.OpenWeatherMapApiKey;
_openWeatherMapKey = options.Value.OpenWeatherMapApiKey;
}

public void Run()
public void Run() => Run(null);

public void Run(string townParm = null)
{
if (String.IsNullOrEmpty(_openWeatherMapKey))
if (String.IsNullOrEmpty(_openWeatherMapKey))
{
Console.WriteLine("Whoops! API key is not defined.");
Console.WriteLine("Get an API key from https://home.openweathermap.org/api_keys then..");
Console.WriteLine("run dotnet user-secrets set \"SecretsModel: OpenWeatherMapApiKey\" \"12345\" to specify your key");
return;
}

Console.Write("Enter your town name:");
string town = (String.IsNullOrEmpty(townParm)) ? Console.ReadLine() : townParm;
string resp = "";
WeatherRoot wr = new WeatherRoot();
try
{
using (var wc = GetWebClient())
{
Console.WriteLine("Whoops! API key is not defined.");
return;
resp = wc.DownloadString($"http://api.openweathermap.org/data/2.5/weather?q={town}&appid={_openWeatherMapKey}");
}
wr = JsonSerializer.Deserialize<WeatherRoot>(resp);
}
catch
{
Console.WriteLine("Got no result or couldn't convert to Weather object");
return;
}

Console.Write("Enter your town name:");
string town = Console.ReadLine();

string resp = "";
Console.WriteLine();
Console.WriteLine("Temperature: " + Weather.KtoF(wr.Main.Temperature) + "°F or " + Weather.KtoC(wr.Main.Temperature) + "°C. Feels like: " + Weather.KtoF(wr.Main.Temperature) + "°F or " + Weather.KtoC(wr.Main.Temperature) + "°C");
Console.WriteLine("Wind speed: " + wr.Wind.Speed + " m/s. Air pressure is " + wr.Main.Pressure + "mmHg or " + Math.Round(wr.Main.Pressure * 133.322, 1) + " Pascals.");

using (var wc = new WebClient())
{
resp = wc.DownloadString($"http://api.openweathermap.org/data/2.5/weather?q={town}&appid={_openWeatherMapKey}");
}
WeatherRoot wr = JsonSerializer.Deserialize<WeatherRoot>(resp);
long currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
bool SunWhat = currentTime > wr.Sys.Sunrise;
long whatNext = SunWhat ? wr.Sys.Sunset : wr.Sys.Sunrise;
long diff = whatNext - currentTime;
var dto = DateTimeOffset.FromUnixTimeSeconds(diff);

Console.WriteLine();
Console.WriteLine("Temperature: " + Weather.KtoF(wr.Main.Temperature) + "°F or " + Weather.KtoC(wr.Main.Temperature) + "°C. Feels like: " + Weather.KtoF(wr.Main.Temperature) + "°F or " + Weather.KtoC(wr.Main.Temperature) + "°C");
Console.WriteLine("Wind speed: " + wr.Wind.Speed + " m/s. Air pressure is " + wr.Main.Pressure + "mmHg or " + Math.Round(wr.Main.Pressure * 133.322, 1) + " Pascals.");
long currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
bool SunWhat = currentTime > wr.Sys.Sunrise;
long whatNext = SunWhat ? wr.Sys.Sunset : wr.Sys.Sunrise;
long diff = whatNext - currentTime;
var dto = DateTimeOffset.FromUnixTimeSeconds(diff);
if (SunWhat) //If sun should be setting...
{
Console.WriteLine("It's day right now. The sun will set in " + dto.ToString("HH:mm:ss"));
}
else
{
Console.WriteLine("It's night right now. The sun will rise in " + dto.ToString("HH:mm:ss"));
}
}

if (SunWhat) //If sun should be setting...
{
Console.WriteLine("It's day right now. The sun will set in " + dto.ToString("HH:mm:ss"));
}
else
{
Console.WriteLine("It's night right now. The sun will rise in " + dto.ToString("HH:mm:ss"));
}
protected virtual IWebClient GetWebClient()
{
var factory = new SystemWebClientFactory();
return factory.Create();
}
}
}