diff --git a/src/.editorconfig b/src/.editorconfig index 042caa1..587aca1 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -11,3 +11,14 @@ dotnet_naming_symbols.any_async_methods.required_modifiers = async dotnet_naming_style.end_in_async.required_suffix = Async dotnet_naming_style.end_in_async.capitalization = pascal_case + +[*.cs] + +# SA1101: Prefix local calls with this +dotnet_diagnostic.SA1101.severity = none + +# SA1309: Field names should not begin with underscore +dotnet_diagnostic.SA1309.severity = none + +# SA1503: Braces should not be omitted +dotnet_diagnostic.SA1503.severity = none diff --git a/src/Tesla.NET/Models/IChargeState.cs b/src/Tesla.NET/Models/IChargeState.cs index 67eb26c..da029d7 100644 --- a/src/Tesla.NET/Models/IChargeState.cs +++ b/src/Tesla.NET/Models/IChargeState.cs @@ -15,19 +15,19 @@ public interface IChargeState : IState /// Gets the charging state of a . /// [JsonProperty("charging_state")] - string ChargingState { get; } + string? ChargingState { get; } /// /// Gets the type of fast charging. /// [JsonProperty("fast_charger_type")] - string FastChargerType { get; } + string? FastChargerType { get; } /// /// Gets the brand of fast charging. /// [JsonProperty("fast_charger_brand")] - string FastChargerBrand { get; } + string? FastChargerBrand { get; } /// /// Gets the charge limit . @@ -171,7 +171,7 @@ public interface IChargeState : IState /// Gets the type of the charge cable connected to a . /// [JsonProperty("conn_charge_cable")] - string ConnChargeCable { get; } + string? ConnChargeCable { get; } /// /// Gets the schedule charging start time of a . @@ -213,7 +213,7 @@ public interface IChargeState : IState /// Gets the charge port latch of a . /// [JsonProperty("charge_port_latch")] - string ChargePortLatch { get; } + string? ChargePortLatch { get; } /// /// Gets the charge current request of a . diff --git a/src/Tesla.NET/Models/IDriveState.cs b/src/Tesla.NET/Models/IDriveState.cs index c8fdd47..488305e 100644 --- a/src/Tesla.NET/Models/IDriveState.cs +++ b/src/Tesla.NET/Models/IDriveState.cs @@ -15,13 +15,13 @@ public interface IDriveState : IState /// Gets the shift state of a . /// [JsonProperty("shift_state")] - string ShiftState { get; } + string? ShiftState { get; } /// /// Gets the speed . /// [JsonProperty("speed")] - string Speed { get; } + string? Speed { get; } /// /// Gets the power . diff --git a/src/Tesla.NET/Models/IMessageResponse.Generic.cs b/src/Tesla.NET/Models/IMessageResponse.Generic.cs index d7baa7d..8fe999a 100644 --- a/src/Tesla.NET/Models/IMessageResponse.Generic.cs +++ b/src/Tesla.NET/Models/IMessageResponse.Generic.cs @@ -15,6 +15,6 @@ public interface IMessageResponse : IMessageResponse /// /// Gets the object. /// - TData Data { get; } + TData? Data { get; } } } diff --git a/src/Tesla.NET/Models/IMessageResponse.cs b/src/Tesla.NET/Models/IMessageResponse.cs index fb14200..9740872 100644 --- a/src/Tesla.NET/Models/IMessageResponse.cs +++ b/src/Tesla.NET/Models/IMessageResponse.cs @@ -20,7 +20,7 @@ public interface IMessageResponse /// /// Gets the raw JSON of the . /// - JObject RawJson { get; } + JObject? RawJson { get; } /// /// Gets the raw JSON of the . diff --git a/src/Tesla.NET/Models/IVehicle.cs b/src/Tesla.NET/Models/IVehicle.cs index 57feb13..c81c9f3 100644 --- a/src/Tesla.NET/Models/IVehicle.cs +++ b/src/Tesla.NET/Models/IVehicle.cs @@ -27,25 +27,25 @@ public interface IVehicle /// Gets the VIN (vehicle identification number) of the . /// [JsonProperty("vin")] - string Vin { get; } + string? Vin { get; } /// /// Gets the display name of the . /// [JsonProperty("display_name")] - string DisplayName { get; } + string? DisplayName { get; } /// /// Gets the option codes of the . /// [JsonProperty("option_codes")] - string OptionCodes { get; } + string? OptionCodes { get; } /// /// Gets the color of the . /// [JsonProperty("color")] - string Color { get; } + string? Color { get; } /// /// Gets the tokens of the . @@ -57,13 +57,13 @@ public interface IVehicle /// Gets the state of the . /// [JsonProperty("state")] - string State { get; } + string? State { get; } /// /// Gets the in service state of the . /// [JsonProperty("in_service")] - string InService { get; } + string? InService { get; } /// /// Gets a value indicating whether remote start is enabled for the . @@ -87,12 +87,12 @@ public interface IVehicle /// Gets the of the . /// [JsonProperty("backseat_token")] - string BackseatToken { get; } + string? BackseatToken { get; } /// /// Gets the of the . /// [JsonProperty("backseat_token_updated_at")] - string BackseatTokenUpdatedAt { get; } + string? BackseatTokenUpdatedAt { get; } } } diff --git a/src/Tesla.NET/Models/IVehicleState.cs b/src/Tesla.NET/Models/IVehicleState.cs index 56e2963..ba3139f 100644 --- a/src/Tesla.NET/Models/IVehicleState.cs +++ b/src/Tesla.NET/Models/IVehicleState.cs @@ -21,19 +21,19 @@ public interface IVehicleState : IState /// Gets the state of auto-park. /// [JsonProperty("autopark_state")] - string AutoparkState { get; } + string? AutoparkState { get; } /// /// Gets the state of V2 auto-park. /// [JsonProperty("autopark_state_v2")] - string AutoparkStateV2 { get; } + string? AutoparkStateV2 { get; } /// /// Gets the style of auto-park. /// [JsonProperty("autopark_style")] - string AutoparkStyle { get; } + string? AutoparkStyle { get; } /// /// Gets a value indicating whether the Calendar is supported. @@ -45,7 +45,7 @@ public interface IVehicleState : IState /// Gets the car firmware version. /// [JsonProperty("car_version")] - string CarVersion { get; } + string? CarVersion { get; } /// /// Gets the state of the center display. @@ -81,7 +81,7 @@ public interface IVehicleState : IState /// Gets the last auto-park error. /// [JsonProperty("last_autopark_error")] - string LastAutoparkError { get; } + string? LastAutoparkError { get; } /// /// Gets a value indicating whether the car is locked. @@ -147,7 +147,7 @@ public interface IVehicleState : IState /// Gets the state of the sunroof. /// [JsonProperty("sun_roof_state")] - string SunRoofState { get; } + string? SunRoofState { get; } /// /// Gets a value indicating whether valet mode is enabled. @@ -165,6 +165,6 @@ public interface IVehicleState : IState /// Gets the name of the . /// [JsonProperty("vehicle_name")] - string VehicleName { get; } + string? VehicleName { get; } } } diff --git a/src/Tesla.NET/Models/Internal/ChargeState.cs b/src/Tesla.NET/Models/Internal/ChargeState.cs index 58bf004..803b063 100644 --- a/src/Tesla.NET/Models/Internal/ChargeState.cs +++ b/src/Tesla.NET/Models/Internal/ChargeState.cs @@ -58,9 +58,9 @@ public class ChargeState : IChargeState /// The . /// The . public ChargeState( - string chargingState = null, - string fastChargerType = null, - string fastChargerBrand = null, + string? chargingState = null, + string? fastChargerType = null, + string? fastChargerBrand = null, long? chargeLimitSoc = null, long? chargeLimitSocStd = null, long? chargeLimitSocMin = null, @@ -84,13 +84,13 @@ public ChargeState( bool? tripCharging = null, long? chargeRate = null, bool? chargePortDoorOpen = null, - string connChargeCable = null, + string? connChargeCable = null, long? scheduledChargingStartTime = null, bool? scheduledChargingPending = null, bool? userChargeEnableRequest = null, bool? chargeEnableRequest = null, int? chargerPhases = null, - string chargePortLatch = null, + string? chargePortLatch = null, long? chargeCurrentRequest = null, long? chargeCurrentRequestMax = null, bool? managedChargingActive = null, @@ -146,17 +146,17 @@ public ChargeState( /// /// Gets the charging state of a . /// - public string ChargingState { get; } + public string? ChargingState { get; } /// /// Gets the type of fast charging. /// - public string FastChargerType { get; } + public string? FastChargerType { get; } /// /// Gets the brand of fast charging. /// - public string FastChargerBrand { get; } + public string? FastChargerBrand { get; } /// /// Gets the charge limit . @@ -276,7 +276,7 @@ public ChargeState( /// /// Gets the type of the charge cable connected to a . /// - public string ConnChargeCable { get; } + public string? ConnChargeCable { get; } /// /// Gets the schedule charging start time of a . @@ -311,7 +311,7 @@ public ChargeState( /// /// Gets the charge port latch of a . /// - public string ChargePortLatch { get; } + public string? ChargePortLatch { get; } /// /// Gets the charge current request of a . diff --git a/src/Tesla.NET/Models/Internal/DriveState.cs b/src/Tesla.NET/Models/Internal/DriveState.cs index 9d8104b..99a0e1f 100644 --- a/src/Tesla.NET/Models/Internal/DriveState.cs +++ b/src/Tesla.NET/Models/Internal/DriveState.cs @@ -24,8 +24,8 @@ public class DriveState : IDriveState /// The . /// The . public DriveState( - string shiftState = null, - string speed = null, + string? shiftState = null, + string? speed = null, long power = 0L, double latitude = 0D, double longitude = 0D, @@ -46,12 +46,12 @@ public DriveState( /// /// Gets the shift state of a . /// - public string ShiftState { get; } + public string? ShiftState { get; } /// /// Gets the speed . /// - public string Speed { get; } + public string? Speed { get; } /// /// Gets the power . diff --git a/src/Tesla.NET/Models/Internal/MessageResponse.cs b/src/Tesla.NET/Models/Internal/MessageResponse.cs index 0da1912..d7207ed 100644 --- a/src/Tesla.NET/Models/Internal/MessageResponse.cs +++ b/src/Tesla.NET/Models/Internal/MessageResponse.cs @@ -17,7 +17,7 @@ namespace Tesla.NET.Models.Internal public class MessageResponse : IMessageResponse where TData : class { - private readonly JObject _rawJson; + private readonly JObject? _rawJson; /// /// Initializes a new instance of the class. @@ -25,7 +25,7 @@ public class MessageResponse : IMessageResponse /// The . /// The raw JSON of the . /// The object. - public MessageResponse(HttpStatusCode httpStatusCode, JObject rawJson = null, TData data = null) + public MessageResponse(HttpStatusCode httpStatusCode, JObject? rawJson = null, TData? data = null) { HttpStatusCode = httpStatusCode; _rawJson = rawJson; @@ -40,7 +40,7 @@ public MessageResponse(HttpStatusCode httpStatusCode, JObject rawJson = null, TD /// /// Gets the raw JSON of the . /// - public JObject RawJson => (JObject)_rawJson?.DeepClone(); + public JObject? RawJson => (JObject?)_rawJson?.DeepClone(); /// /// Gets the raw JSON of the . @@ -50,7 +50,7 @@ public MessageResponse(HttpStatusCode httpStatusCode, JObject rawJson = null, TD /// /// Gets the object. /// - public TData Data { get; } + public TData? Data { get; } private string DebuggerDisplay => $"{GetType().Name}: {HttpStatusCode:G}"; } diff --git a/src/Tesla.NET/Models/Internal/ResponseDataWrapper.cs b/src/Tesla.NET/Models/Internal/ResponseDataWrapper.cs index 9a9a38f..f0f9df7 100644 --- a/src/Tesla.NET/Models/Internal/ResponseDataWrapper.cs +++ b/src/Tesla.NET/Models/Internal/ResponseDataWrapper.cs @@ -17,7 +17,7 @@ public class ResponseDataWrapper : IResponseDataWrapper /// Initializes a new instance of the class. /// /// The object. - public ResponseDataWrapper(TResponse response = default) + public ResponseDataWrapper(TResponse response) { Response = response; } diff --git a/src/Tesla.NET/Models/Internal/Vehicle.cs b/src/Tesla.NET/Models/Internal/Vehicle.cs index 410828a..02b647c 100644 --- a/src/Tesla.NET/Models/Internal/Vehicle.cs +++ b/src/Tesla.NET/Models/Internal/Vehicle.cs @@ -3,6 +3,7 @@ namespace Tesla.NET.Models.Internal { + using System; using System.Collections.Generic; using System.Diagnostics; @@ -12,7 +13,7 @@ namespace Tesla.NET.Models.Internal [DebuggerDisplay("{DebuggerDisplay,nq}")] public class Vehicle : IVehicle { - private static readonly string[] EmptyTokens = { }; + private static readonly string[] EmptyTokens = Array.Empty(); /// /// Initializes a new instance of the class. @@ -34,18 +35,18 @@ public class Vehicle : IVehicle public Vehicle( long id = 0, long vehicleId = 0, - string vin = null, - string displayName = null, - string optionCodes = null, - string color = null, - IReadOnlyCollection tokens = null, - string state = null, - string inService = null, + string? vin = null, + string? displayName = null, + string? optionCodes = null, + string? color = null, + IReadOnlyCollection? tokens = null, + string? state = null, + string? inService = null, bool remoteStartEnabled = false, bool calendarEnabled = false, bool notificationsEnabled = false, - string backseatToken = null, - string backseatTokenUpdatedAt = null) + string? backseatToken = null, + string? backseatTokenUpdatedAt = null) { Id = id; VehicleId = vehicleId; @@ -76,22 +77,22 @@ public Vehicle( /// /// Gets the VIN (vehicle identification number) of the . /// - public string Vin { get; } + public string? Vin { get; } /// /// Gets the display name of the . /// - public string DisplayName { get; } + public string? DisplayName { get; } /// /// Gets the option codes of the . /// - public string OptionCodes { get; } + public string? OptionCodes { get; } /// /// Gets the color of the . /// - public string Color { get; } + public string? Color { get; } /// /// Gets the tokens of the . @@ -101,12 +102,12 @@ public Vehicle( /// /// Gets the state of the . /// - public string State { get; } + public string? State { get; } /// /// Gets the in service state of the . /// - public string InService { get; } + public string? InService { get; } /// /// Gets a value indicating whether remote start is enabled for the . @@ -126,12 +127,12 @@ public Vehicle( /// /// Gets the of the . /// - public string BackseatToken { get; } + public string? BackseatToken { get; } /// /// Gets the of the . /// - public string BackseatTokenUpdatedAt { get; } + public string? BackseatTokenUpdatedAt { get; } private string DebuggerDisplay => $"{GetType().Name}: {DisplayName} VIN={Vin}"; } diff --git a/src/Tesla.NET/Models/Internal/VehicleState.cs b/src/Tesla.NET/Models/Internal/VehicleState.cs index 0b89cfc..17885a1 100644 --- a/src/Tesla.NET/Models/Internal/VehicleState.cs +++ b/src/Tesla.NET/Models/Internal/VehicleState.cs @@ -44,17 +44,17 @@ public class VehicleState : IVehicleState /// The . public VehicleState( long apiVersion = default, - string autoparkState = default, - string autoparkStateV2 = default, - string autoparkStyle = default, + string? autoparkState = default, + string? autoparkStateV2 = default, + string? autoparkStyle = default, bool calendarSupported = default, - string carVersion = default, + string? carVersion = default, long centerDisplayState = default, long df = default, long dr = default, long ft = default, bool homelinkNearby = default, - string lastAutoparkError = default, + string? lastAutoparkError = default, bool locked = default, bool notificationsSupported = default, double odometer = default, @@ -65,11 +65,11 @@ public VehicleState( bool remoteStartSupported = default, long rt = default, long? sunRoofPercentOpen = default, - string sunRoofState = default, + string? sunRoofState = default, long timestamp = default, bool valetMode = default, bool valetPinNeeded = default, - string vehicleName = default) + string? vehicleName = default) { ApiVersion = apiVersion; AutoparkState = autoparkState ?? string.Empty; @@ -108,17 +108,17 @@ public VehicleState( /// /// Gets the state of auto-park. /// - public string AutoparkState { get; } + public string? AutoparkState { get; } /// /// Gets the state of V2 auto-park. /// - public string AutoparkStateV2 { get; } + public string? AutoparkStateV2 { get; } /// /// Gets the style of auto-park. /// - public string AutoparkStyle { get; } + public string? AutoparkStyle { get; } /// /// Gets a value indicating whether the Calendar is supported. @@ -128,7 +128,7 @@ public VehicleState( /// /// Gets the car firmware version. /// - public string CarVersion { get; } + public string? CarVersion { get; } /// /// Gets the state of the center display. @@ -158,7 +158,7 @@ public VehicleState( /// /// Gets the last auto-park error. /// - public string LastAutoparkError { get; } + public string? LastAutoparkError { get; } /// /// Gets a value indicating whether the car is locked. @@ -213,7 +213,7 @@ public VehicleState( /// /// Gets the state of the sunroof. /// - public string SunRoofState { get; } + public string? SunRoofState { get; } /// /// Gets the millisecond Epoch timestamp when the was captured. @@ -238,7 +238,7 @@ public VehicleState( /// /// Gets the name of the . /// - public string VehicleName { get; } + public string? VehicleName { get; } private string DebuggerDisplay => $"{GetType().Name}: {VehicleName} {CarVersion} @ {TimestampUtc:R}"; } diff --git a/src/Tesla.NET/Properties/AssemblyInfo.cs b/src/Tesla.NET/Properties/AssemblyInfo.cs index 589d654..50ce6c6 100644 --- a/src/Tesla.NET/Properties/AssemblyInfo.cs +++ b/src/Tesla.NET/Properties/AssemblyInfo.cs @@ -7,17 +7,13 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -#if NET45 -[assembly: AssemblyTitle("Tesla.NET .NET Framework")] -#else -[assembly: AssemblyTitle("Tesla.NET .NET Standard")] -#endif +[assembly: AssemblyTitle("Tesla.NET")] [assembly: AssemblyDescription("A .NET client library for the Tesla Owner API.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Tesla.NET")] -[assembly: AssemblyCopyright("Copyright © 2018 James Skimming")] +[assembly: AssemblyCopyright("Copyright © 2018-2021 James Skimming")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/src/Tesla.NET/Requests/HttpClientExtensions.cs b/src/Tesla.NET/Requests/HttpClientExtensions.cs index fc0bb28..d8608c0 100644 --- a/src/Tesla.NET/Requests/HttpClientExtensions.cs +++ b/src/Tesla.NET/Requests/HttpClientExtensions.cs @@ -5,6 +5,7 @@ namespace Tesla.NET.Requests { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net; @@ -57,20 +58,20 @@ public static Task> RequestAccessTokenAsy throw new ArgumentNullException(nameof(password)); Uri requestUri = new Uri(baseUri, "oauth/token"); - IEnumerable> parameters = GetRequestAccessTokenParameters(); + IEnumerable> parameters = GetRequestAccessTokenParameters(); return client .PostFormAsync(requestUri, parameters, cancellationToken: cancellationToken) .ReadJsonAsAsync(cancellationToken); - IEnumerable> GetRequestAccessTokenParameters() + IEnumerable> GetRequestAccessTokenParameters() { - yield return new KeyValuePair("grant_type", "password"); - yield return new KeyValuePair("client_id", clientId); - yield return new KeyValuePair("client_secret", clientSecret); - yield return new KeyValuePair("email", email); - yield return new KeyValuePair("password", password); + yield return new KeyValuePair("grant_type", "password"); + yield return new KeyValuePair("client_id", clientId); + yield return new KeyValuePair("client_secret", clientSecret); + yield return new KeyValuePair("email", email); + yield return new KeyValuePair("password", password); } } @@ -105,19 +106,19 @@ public static Task> RefreshAccessTokenAsy throw new ArgumentNullException(nameof(refreshToken)); Uri requestUri = new Uri(baseUri, "oauth/token"); - IEnumerable> parameters = GetRefreshAccessTokenParameters(); + IEnumerable> parameters = GetRefreshAccessTokenParameters(); return client .PostFormAsync(requestUri, parameters, cancellationToken: cancellationToken) .ReadJsonAsAsync(cancellationToken); - IEnumerable> GetRefreshAccessTokenParameters() + IEnumerable> GetRefreshAccessTokenParameters() { - yield return new KeyValuePair("grant_type", "refresh_token"); - yield return new KeyValuePair("client_id", clientId); - yield return new KeyValuePair("client_secret", clientSecret); - yield return new KeyValuePair("refresh_token", refreshToken); + yield return new KeyValuePair("grant_type", "refresh_token"); + yield return new KeyValuePair("client_id", clientId); + yield return new KeyValuePair("client_secret", clientSecret); + yield return new KeyValuePair("refresh_token", refreshToken); } } @@ -145,16 +146,16 @@ public static Task> RevokeAccessTokenAsync( Uri requestUri = new Uri(baseUri, "oauth/revoke"); - IEnumerable> parameters = GetRevokeAccessTokenParameters(); + IEnumerable> parameters = GetRevokeAccessTokenParameters(); return client .PostFormAsync(requestUri, parameters, accessToken, cancellationToken) .ReadJsonAsAsync(cancellationToken); - IEnumerable> GetRevokeAccessTokenParameters() + IEnumerable> GetRevokeAccessTokenParameters() { - yield return new KeyValuePair("token", accessToken); + yield return new KeyValuePair("token", accessToken); } } @@ -173,7 +174,7 @@ IEnumerable> GetRevokeAccessTokenParameters() public static Task>>> GetVehiclesAsync( this HttpClient client, Uri baseUri, - string accessToken = null, + string? accessToken = null, CancellationToken cancellationToken = default) { if (client == null) @@ -210,7 +211,7 @@ public static Task>> GetChar this HttpClient client, Uri baseUri, long vehicleId, - string accessToken = null, + string? accessToken = null, CancellationToken cancellationToken = default) { if (client == null) @@ -247,7 +248,7 @@ public static Task>> GetDrive this HttpClient client, Uri baseUri, long vehicleId, - string accessToken = null, + string? accessToken = null, CancellationToken cancellationToken = default) { if (client == null) @@ -284,7 +285,7 @@ public static Task>> GetVeh this HttpClient client, Uri baseUri, long vehicleId, - string accessToken = null, + string? accessToken = null, CancellationToken cancellationToken = default) { if (client == null) @@ -317,8 +318,8 @@ public static Task>> GetVeh private static async Task PostFormAsync( this HttpClient client, Uri requestUri, - IEnumerable> parameters, - string accessToken = null, + IEnumerable> parameters, + string? accessToken = null, CancellationToken cancellationToken = default) { if (client == null) @@ -362,7 +363,7 @@ private static async Task PostFormAsync( private static async Task GetWithAuthAsync( this HttpClient client, Uri requestUri, - string accessToken = null, + string? accessToken = null, CancellationToken cancellationToken = default) { if (client == null) @@ -436,7 +437,7 @@ private static async Task> ReadSuccessResponseAsync( JObject rawJson = await ReadJsonAsync(responseMessage, cancellationToken).ConfigureAwait(false); JsonSerializer serializer = JsonSerializer.CreateDefault(); - T data = rawJson.ToObject(serializer); + T? data = rawJson.ToObject(serializer); IMessageResponse response = new MessageResponse(responseMessage.StatusCode, rawJson, data); return response; @@ -451,6 +452,10 @@ private static async Task> ReadSuccessResponseAsync( /// A to observe while waiting for a task to /// complete. /// The . + [SuppressMessage( + "Design", + "CA1031:Do not catch general exception types", + Justification = "Exception swallowed to return error code.")] private static async Task> ReadFailureResponseAsync( this HttpResponseMessage responseMessage, CancellationToken cancellationToken) @@ -459,7 +464,7 @@ private static async Task> ReadFailureResponseAsync( if (responseMessage == null) throw new ArgumentNullException(nameof(responseMessage)); - JObject rawJson = null; + JObject? rawJson = null; try { // Check the content is JSON, and the response was not Unauthorized as the API returns a Content-Type @@ -492,7 +497,7 @@ private static bool IsContentJson(HttpResponseMessage responseMessage) if (responseMessage == null) throw new ArgumentNullException(nameof(responseMessage)); - string mediaType = responseMessage.Content?.Headers.ContentType.MediaType; + string? mediaType = responseMessage.Content.Headers.ContentType?.MediaType; return string.Equals(mediaType, "application/json", StringComparison.OrdinalIgnoreCase); } diff --git a/src/Tesla.NET/Tesla.NET.csproj b/src/Tesla.NET/Tesla.NET.csproj index 602cddc..dddcc4f 100644 --- a/src/Tesla.NET/Tesla.NET.csproj +++ b/src/Tesla.NET/Tesla.NET.csproj @@ -1,10 +1,11 @@  - net45;netstandard2.0 + net5.0 latest true true + enable ..\stylecop.ruleset false James Skimming, Patrik Pfaffenbauer @@ -18,27 +19,18 @@ tesla tesla-api dotnet dotnet-core - - - pdbonly - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - + all - runtime; build; native; contentfiles; analyzers + runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - diff --git a/src/Tesla.NET/TeslaClientBase.Disposable.cs b/src/Tesla.NET/TeslaClientBase.Disposable.cs index 9eabc13..91a6aa9 100644 --- a/src/Tesla.NET/TeslaClientBase.Disposable.cs +++ b/src/Tesla.NET/TeslaClientBase.Disposable.cs @@ -37,11 +37,8 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - Client?.Dispose(); + Client.Dispose(); } - - Client = null; - BaseUri = null; } } } diff --git a/src/Tesla.NET/TeslaClientBase.cs b/src/Tesla.NET/TeslaClientBase.cs index 32ace85..bbf168d 100644 --- a/src/Tesla.NET/TeslaClientBase.cs +++ b/src/Tesla.NET/TeslaClientBase.cs @@ -62,12 +62,12 @@ protected TeslaClientBase(Uri baseUri, HttpClient client) /// /// Gets the base of the Tesla Owner API. /// - public Uri BaseUri { get; private set; } + public Uri BaseUri { get; } /// /// Gets the underlying HttpClient used to make requests. /// - public HttpClient Client { get; private set; } + public HttpClient Client { get; } /// /// Transform a collection of s into a chain of @@ -94,16 +94,15 @@ public static HttpMessageHandler CreatePipeline(IReadOnlyCollection reversedHandlers = handlers.Reverse().Skip(1); foreach (HttpMessageHandler handler in reversedHandlers) { - dHandler = handler as DelegatingHandler; - if (dHandler == null) + if (!(handler is DelegatingHandler next)) { throw new ArgumentException( $"All message handlers except the last must be of type '{typeof(DelegatingHandler).Name}'.", nameof(handlers)); } - dHandler.InnerHandler = pipeline; - pipeline = dHandler; + next.InnerHandler = pipeline; + pipeline = next; } return pipeline; diff --git a/src/stylecop.ruleset b/src/stylecop.ruleset index af484b6..be62c0f 100644 --- a/src/stylecop.ruleset +++ b/src/stylecop.ruleset @@ -1,9 +1,8 @@  - + - - - + + \ No newline at end of file diff --git a/test/.editorconfig b/test/.editorconfig new file mode 100644 index 0000000..fecf530 --- /dev/null +++ b/test/.editorconfig @@ -0,0 +1,40 @@ +[*.cs] + +# SA1101: Prefix local calls with this +dotnet_diagnostic.SA1101.severity = none + +# SA1300: Element should begin with upper-case letter +dotnet_diagnostic.SA1300.severity = none + +# SA1309: Field names should not begin with underscore +dotnet_diagnostic.SA1309.severity = none + +# SA1402: File may only contain a single type +dotnet_diagnostic.SA1402.severity = none + +# SA1503: Braces should not be omitted +dotnet_diagnostic.SA1503.severity = none + +# SA1600: Elements should be documented +dotnet_diagnostic.SA1600.severity = none + +# SA1611: Element parameters should be documented +dotnet_diagnostic.SA1611.severity = none + +# SA1615: Element return value should be documented +dotnet_diagnostic.SA1615.severity = none + +# SA1623: Property summary documentation should match accessors +dotnet_diagnostic.SA1623.severity = none + +# SA1649: File name should match first type name +dotnet_diagnostic.SA1649.severity = none + +# CA1303: Do not pass literals as localized parameters +dotnet_diagnostic.CA1303.severity = none + +# CA1707: Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = none + +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = none diff --git a/test/Tesla.NET.Tests/DebuggerDisplayTests.cs b/test/Tesla.NET.Tests/DebuggerDisplayTests.cs index 6335c3f..9f84d5a 100644 --- a/test/Tesla.NET.Tests/DebuggerDisplayTests.cs +++ b/test/Tesla.NET.Tests/DebuggerDisplayTests.cs @@ -12,33 +12,18 @@ namespace Tesla.NET public abstract class DebuggerDisplayTestsBase : FixtureContext { - private Type _sutType; - private DebuggerDisplayAttribute _debuggerDisplay; - private PropertyInfo _debuggerDisplayPropertyInfo; - private MethodInfo _debuggerDisplayGetMethod; - private object _debuggerDisplayValue; - protected string DebuggerDisplayText; + private Type? _sutType; + private DebuggerDisplayAttribute? _debuggerDisplay; + private PropertyInfo? _debuggerDisplayPropertyInfo; + private MethodInfo? _debuggerDisplayGetMethod; + private object? _debuggerDisplayValue; protected DebuggerDisplayTestsBase(ITestOutputHelper output) : base(output) { } - protected void GetDebuggerDisplay(TSut sut) - { - _sutType = sut.GetType(); - - _debuggerDisplay = _sutType.GetTypeInfo().GetCustomAttribute(inherit: false); - - _debuggerDisplayPropertyInfo = - _sutType.GetProperty("DebuggerDisplay", BindingFlags.NonPublic | BindingFlags.Instance); - - _debuggerDisplayGetMethod = _debuggerDisplayPropertyInfo.GetGetMethod(true); - - _debuggerDisplayValue = _debuggerDisplayGetMethod.Invoke(sut, new object[] { }); - - DebuggerDisplayText = _debuggerDisplayValue.ToString(); - } + protected string? DebuggerDisplayText { get; private set; } [Fact] public void have_the_debugger_display_attribute() @@ -49,6 +34,8 @@ public void have_the_debugger_display_attribute() [Fact] public void specify_the_debugger_display_property() { + if (_debuggerDisplay is null) throw new InvalidOperationException(nameof(_debuggerDisplay) + " is null"); + _debuggerDisplay.Value.Should().BeEquivalentTo("{DebuggerDisplay,nq}"); } @@ -73,7 +60,25 @@ public void provide_a_string_debugger_display_property() [Fact] public void include_the_type_in_the_debugger_display() { + if (_sutType is null) throw new InvalidOperationException(nameof(_sutType) + " is null"); + DebuggerDisplayText.Should().StartWith($"{_sutType.Name}:"); } + + protected void GetDebuggerDisplay(TSut sut) + { + _sutType = sut?.GetType(); + + _debuggerDisplay = _sutType?.GetCustomAttribute(inherit: false); + + _debuggerDisplayPropertyInfo = + _sutType?.GetProperty("DebuggerDisplay", BindingFlags.NonPublic | BindingFlags.Instance); + + _debuggerDisplayGetMethod = _debuggerDisplayPropertyInfo?.GetGetMethod(true); + + _debuggerDisplayValue = _debuggerDisplayGetMethod?.Invoke(sut, new object[] { }); + + DebuggerDisplayText = _debuggerDisplayValue?.ToString(); + } } } diff --git a/test/Tesla.NET.Tests/FixedContructorArgument.cs b/test/Tesla.NET.Tests/FixedContructorArgument.cs index 6a4e269..02433ea 100644 --- a/test/Tesla.NET.Tests/FixedContructorArgument.cs +++ b/test/Tesla.NET.Tests/FixedContructorArgument.cs @@ -41,7 +41,7 @@ public FixedContructorArgument(string parameterName, Func valueF _valueFunc = valueFunc ?? throw new ArgumentNullException(nameof(valueFunc)); } - public object Create(object request, ISpecimenContext context) + public object? Create(object request, ISpecimenContext context) { if (!(request is ParameterInfo pi)) return new NoSpecimen(); diff --git a/test/Tesla.NET.Tests/GetChargeStateTests.cs b/test/Tesla.NET.Tests/GetChargeStateTests.cs index ece46ef..c583a6c 100644 --- a/test/Tesla.NET.Tests/GetChargeStateTests.cs +++ b/test/Tesla.NET.Tests/GetChargeStateTests.cs @@ -73,8 +73,8 @@ public async Task Should_set_the_bearer_token_with_the_specified_access_token() await Sut.GetChargeStateAsync(_vehicleId, AccessToken).ConfigureAwait(false); // Assert - Handler.Request.Headers.Authorization.Scheme.Should().Be("Bearer"); - Handler.Request.Headers.Authorization.Parameter.Should().Be(AccessToken); + Handler.Request.Headers.Authorization?.Scheme.Should().Be("Bearer"); + Handler.Request.Headers.Authorization?.Parameter.Should().Be(AccessToken); } [Fact] @@ -160,7 +160,8 @@ public When_getting_the_charge_state_for_a_vehicle_the_raw_JSON(ITestOutputHelpe // Add random values to test whether it is correctly passed through. _expected["randomValue1"] = Fixture.Create("randomValue1"); _expected["randomValue2"] = JObject.FromObject(new { fakeId = Guid.NewGuid() }); - _expected["response"]["randomValue3"] = Fixture.Create("randomValue3"); + JToken response = _expected["response"] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("randomValue3"); Handler.SetResponseContent(_expected); } diff --git a/test/Tesla.NET.Tests/GetDriveStateTests.cs b/test/Tesla.NET.Tests/GetDriveStateTests.cs index 7bd08f1..8e1f427 100644 --- a/test/Tesla.NET.Tests/GetDriveStateTests.cs +++ b/test/Tesla.NET.Tests/GetDriveStateTests.cs @@ -73,8 +73,8 @@ public async Task Should_set_the_bearer_token_with_the_specified_access_token() await Sut.GetDriveStateAsync(_vehicleId, AccessToken).ConfigureAwait(false); // Assert - Handler.Request.Headers.Authorization.Scheme.Should().Be("Bearer"); - Handler.Request.Headers.Authorization.Parameter.Should().Be(AccessToken); + Handler.Request.Headers.Authorization?.Scheme.Should().Be("Bearer"); + Handler.Request.Headers.Authorization?.Parameter.Should().Be(AccessToken); } [Fact] @@ -160,7 +160,8 @@ public When_getting_the_drive_state_for_a_vehicle_the_raw_JSON(ITestOutputHelper // Add random values to test whether it is correctly passed through. _expected["randomValue1"] = Fixture.Create("randomValue1"); _expected["randomValue2"] = JObject.FromObject(new { fakeId = Guid.NewGuid() }); - _expected["response"]["randomValue3"] = Fixture.Create("randomValue3"); + JToken response = _expected["response"] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("randomValue3"); Handler.SetResponseContent(_expected); } diff --git a/test/Tesla.NET.Tests/GetVehicleStateTests.cs b/test/Tesla.NET.Tests/GetVehicleStateTests.cs index 41f2364..65033f4 100644 --- a/test/Tesla.NET.Tests/GetVehicleStateTests.cs +++ b/test/Tesla.NET.Tests/GetVehicleStateTests.cs @@ -73,8 +73,8 @@ public async Task Should_set_the_bearer_token_with_the_specified_access_token() await Sut.GetVehicleStateAsync(_vehicleId, AccessToken).ConfigureAwait(false); // Assert - Handler.Request.Headers.Authorization.Scheme.Should().Be("Bearer"); - Handler.Request.Headers.Authorization.Parameter.Should().Be(AccessToken); + Handler.Request.Headers.Authorization?.Scheme.Should().Be("Bearer"); + Handler.Request.Headers.Authorization?.Parameter.Should().Be(AccessToken); } [Fact] @@ -160,7 +160,8 @@ public When_getting_the_vehicle_state_for_a_vehicle_the_raw_JSON(ITestOutputHelp // Add random values to test whether it is correctly passed through. _expected["randomValue1"] = Fixture.Create("randomValue1"); _expected["randomValue2"] = JObject.FromObject(new { fakeId = Guid.NewGuid() }); - _expected["response"]["randomValue3"] = Fixture.Create("randomValue3"); + JToken response = _expected["response"] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("randomValue3"); Handler.SetResponseContent(_expected); } @@ -191,7 +192,8 @@ public When_getting_the_vehicle_state_for_a_vehicle_the_raw_JSON_with_null_value // Add random values to test whether it is correctly passed through. _expected["randomValue1"] = Fixture.Create("randomValue1"); _expected["randomValue2"] = JObject.FromObject(new { fakeId = Guid.NewGuid() }); - _expected["response"]["randomValue3"] = Fixture.Create("randomValue3"); + JToken response = _expected["response"] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("randomValue3"); Handler.SetResponseContent(_expected); } @@ -202,6 +204,8 @@ public async Task Should_be_passed_through_in_the_response() // Act IMessageResponse> response = await Sut.GetVehicleStateAsync(_vehicleId).ConfigureAwait(false); + if (response.Data is null) throw new InvalidOperationException("response data is null."); + response.Data.Response.SunRoofPercentOpen.Should().Be(null); // Assert diff --git a/test/Tesla.NET.Tests/GetVehiclesTests.cs b/test/Tesla.NET.Tests/GetVehiclesTests.cs index 6f82238..5a281d7 100644 --- a/test/Tesla.NET.Tests/GetVehiclesTests.cs +++ b/test/Tesla.NET.Tests/GetVehiclesTests.cs @@ -71,8 +71,8 @@ public async Task Should_set_the_bearer_token_with_the_specified_access_token() await Sut.GetVehiclesAsync(AccessToken).ConfigureAwait(false); // Assert - Handler.Request.Headers.Authorization.Scheme.Should().Be("Bearer"); - Handler.Request.Headers.Authorization.Parameter.Should().Be(AccessToken); + Handler.Request.Headers.Authorization?.Scheme.Should().Be("Bearer"); + Handler.Request.Headers.Authorization?.Parameter.Should().Be(AccessToken); } [Fact] @@ -153,7 +153,8 @@ public When_getting_the_vehicles_for_an_account_the_raw_JSON(ITestOutputHelper o // Add random values to test whether it is correctly passed through. _expected["randomValue1"] = Fixture.Create("randomValue1"); _expected["randomValue2"] = JObject.FromObject(new { fakeId = Guid.NewGuid() }); - _expected["response"][0]["randomValue3"] = Fixture.Create("randomValue3"); + JToken response = _expected["response"]?[0] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("randomValue3"); Handler.SetResponseContent(_expected); } diff --git a/test/Tesla.NET.Tests/HttpHandlers/ForcedAsyncStream.cs b/test/Tesla.NET.Tests/HttpHandlers/ForcedAsyncStream.cs index 4d5776e..610d171 100644 --- a/test/Tesla.NET.Tests/HttpHandlers/ForcedAsyncStream.cs +++ b/test/Tesla.NET.Tests/HttpHandlers/ForcedAsyncStream.cs @@ -79,7 +79,6 @@ protected override void Dispose(bool disposing) _inner?.Dispose(); } - _inner = null; base.Dispose(disposing); } } diff --git a/test/Tesla.NET.Tests/HttpHandlers/TestHttpHandler.cs b/test/Tesla.NET.Tests/HttpHandlers/TestHttpHandler.cs index 4e8995f..1714604 100644 --- a/test/Tesla.NET.Tests/HttpHandlers/TestHttpHandler.cs +++ b/test/Tesla.NET.Tests/HttpHandlers/TestHttpHandler.cs @@ -17,63 +17,126 @@ namespace Tesla.NET.HttpHandlers using Newtonsoft.Json.Linq; using Xunit.Abstractions; + /// + /// A test that records requests and returned fixed responses. + /// public class TestHttpHandler : HttpMessageHandler { private readonly ITestOutputHelper _output; private int _responseIndex; + /// + /// Initializes a new instance of the class. + /// + /// The . public TestHttpHandler(ITestOutputHelper output) { _output = output ?? throw new ArgumentNullException(nameof(output)); } + /// + /// Gets or sets the last received request. + /// public HttpRequestMessage Request { - get => Requests.Count == 0 ? null : Requests[Requests.Count - 1]; + get + { + if (Requests.Count == 0) + throw new InvalidOperationException("There are no requests to return."); + + return Requests[Requests.Count - 1]; + } + set { + if (value is null) + throw new ArgumentNullException(nameof(value)); + Requests.Clear(); Requests.Add(value); } } + /// + /// Gets the list of received requests. + /// public List Requests { get; } = new List(1); + /// + /// Gets the list of fixed responses. + /// public List Responses { get; } = new List(1); - public List RequestContents { get; } = new List(1); + /// + /// Gets the list of request contents. + /// + public List RequestContents { get; } = new List(1); + /// + /// Gets or sets the last fixed response. + /// public HttpResponseMessage Response { - get => Responses.Count == 0 ? null : Responses[Responses.Count - 1]; + get + { + if (Responses.Count == 0) + throw new InvalidOperationException("There are no responses to return."); + + return Responses[Responses.Count - 1]; + } + set { + if (value is null) + throw new ArgumentNullException(nameof(value)); + _responseIndex = 0; Responses.Clear(); Responses.Add(value); } } - public Func> OnSendingRequest { get; set; } + /// + /// Get or sets a function to intercept request sending. + /// + public Func>? OnSendingRequest { get; set; } + /// + /// Sets the fixed response with the specified . + /// + /// The response to use. public void SetResponse(HttpStatusCode code) => SetResponseContent(null, code); - public void SetResponseContent(object content, HttpStatusCode code = HttpStatusCode.OK) + /// + /// Sets the fixed response with the specified and . + /// + /// The response content to use. + /// The response to use. + public void SetResponseContent(object? content, HttpStatusCode code = HttpStatusCode.OK) { Response = CreateResponse(content, code); } + /// + /// Adds the fixed response with the specified and . + /// + /// The response content to use. + /// The response to use. public void AddResponseContent(object content, HttpStatusCode code = HttpStatusCode.OK) { Responses.Add(CreateResponse(content, code)); } + /// protected override async Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { - string requestContent = await GetStringContent(request.Content).ConfigureAwait(false); + if (request is null) + throw new ArgumentNullException(nameof(request)); + + string? requestContent = await GetStringContent(request.Content).ConfigureAwait(false); RequestContents.Add(requestContent); _output.WriteLine($"Started {request.Method} '{request.RequestUri}'"); @@ -97,7 +160,7 @@ protected override async Task SendAsync( HttpResponseMessage responseMessage = _responseIndex < Responses.Count ? Responses[_responseIndex++] - : CreateResponse(string.Empty); + : CreateResponse("{}"); responseMessage.RequestMessage = request; @@ -105,7 +168,7 @@ protected override async Task SendAsync( $"Completed {request.Method} '{request.RequestUri}' " + $"with {responseMessage.StatusCode:G} ({responseMessage.StatusCode:D})"); - string responseContent = await GetStringContent(responseMessage.Content).ConfigureAwait(false); + string? responseContent = await GetStringContent(responseMessage.Content).ConfigureAwait(false); if (responseContent != null) { _output.WriteLine(responseContent); @@ -114,15 +177,15 @@ protected override async Task SendAsync( return responseMessage; } - private static async Task GetStringContent(HttpContent content) + private static async Task GetStringContent(HttpContent? content) { - if (content == null) + if (content is null) return null; string contentData; if (content is ForcedAsyncStreamContent delayedContent) { - using (var s = new StreamReader(delayedContent.Stream, Encoding.UTF8, true, 10240, leaveOpen:true)) + using (var s = new StreamReader(delayedContent.Stream, Encoding.UTF8, true, 10240, leaveOpen: true)) { contentData = s.ReadToEnd(); } @@ -134,7 +197,8 @@ private static async Task GetStringContent(HttpContent content) contentData = await content.ReadAsStringAsync().ConfigureAwait(false); } - bool? isJson = content.Headers?.ContentType?.ToString().Equals("application/json"); + bool? isJson = content.Headers?.ContentType?.ToString() + .Equals("application/json", StringComparison.OrdinalIgnoreCase); if (isJson.GetValueOrDefault()) { contentData = JToken.Parse(contentData).ToString(Formatting.Indented); @@ -143,9 +207,9 @@ private static async Task GetStringContent(HttpContent content) return contentData; } - private static HttpResponseMessage CreateResponse(object content, HttpStatusCode code = HttpStatusCode.OK) + private static HttpResponseMessage CreateResponse(object? content, HttpStatusCode code = HttpStatusCode.OK) { - if (content == null) + if (content is null) { return new HttpResponseMessage(code); } @@ -166,7 +230,7 @@ private static HttpResponseMessage CreateResponse(object content, HttpStatusCode Headers = { ContentType = new MediaTypeHeaderValue("application/json"), - } + }, }; return new HttpResponseMessage(code) diff --git a/test/Tesla.NET.Tests/InvalidJsonResponseTests.cs b/test/Tesla.NET.Tests/InvalidJsonResponseTests.cs index bf0531a..27666e5 100644 --- a/test/Tesla.NET.Tests/InvalidJsonResponseTests.cs +++ b/test/Tesla.NET.Tests/InvalidJsonResponseTests.cs @@ -25,7 +25,7 @@ public abstract class InvalidJsonResponseTestsBase : ClientRequestContext private readonly HttpStatusCode _statusCode; protected InvalidJsonResponseTestsBase(ITestOutputHelper output, HttpStatusCode statusCode) - : base(output, useCustomBaseUri : false) + : base(output, useCustomBaseUri: false) { // Arrange _statusCode = statusCode; @@ -33,6 +33,26 @@ protected InvalidJsonResponseTestsBase(ITestOutputHelper output, HttpStatusCode Handler.Response = CreateResponse(statusCode); } + [Fact] + public async Task It_should_return_just_the_HTTP_status_Code() + { + // Act + IMessageResponse actual = await Sut.GetVehicleStateAsync(_vehicleId, AccessToken).ConfigureAwait(false); + + // Assert + actual.HttpStatusCode.Should().Be(_statusCode); + } + + [Fact] + public void It_should_not_throw_an_exception() + { + // Act + Func action = () => Sut.GetVehicleStateAsync(_vehicleId, AccessToken); + + // Assert + action.Should().NotThrow(); + } + private static HttpResponseMessage CreateResponse(HttpStatusCode statusCode) { string stringContent = "0" + Environment.NewLine + Environment.NewLine; @@ -49,7 +69,7 @@ private static HttpResponseMessage CreateResponse(HttpStatusCode statusCode) Headers = { ContentType = new MediaTypeHeaderValue("application/json"), - } + }, }; HttpResponseMessage response = new HttpResponseMessage(statusCode) @@ -58,26 +78,6 @@ private static HttpResponseMessage CreateResponse(HttpStatusCode statusCode) }; return response; } - - [Fact] - public async Task It_should_return_just_the_HTTP_status_Code() - { - // Act - IMessageResponse actual = await Sut.GetVehicleStateAsync(_vehicleId, AccessToken).ConfigureAwait(false); - - // Assert - actual.HttpStatusCode.Should().Be(_statusCode); - } - - [Fact] - public void It_should_not_throw_an_exception() - { - // Act - Func action = () => Sut.GetVehicleStateAsync(_vehicleId, AccessToken); - - // Assert - action.Should().NotThrow(); - } } /// diff --git a/test/Tesla.NET.Tests/Models/Internal/AccessTokenResponseTests.cs b/test/Tesla.NET.Tests/Models/Internal/AccessTokenResponseTests.cs index fe93f5a..f62ed05 100644 --- a/test/Tesla.NET.Tests/Models/Internal/AccessTokenResponseTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/AccessTokenResponseTests.cs @@ -30,19 +30,21 @@ public When_serializing_AccessTokenResponse_Should_serialize(ITestOutputHelper o public void five_properties() => _json.Count.Should().Be(5); [Fact] - public void access_token() => _json["access_token"].Value().Should().Be(_sut.AccessToken); + public void access_token() => Get("access_token").Value().Should().Be(_sut.AccessToken); [Fact] - public void token_type() => _json["token_type"].Value().Should().Be(_sut.TokenType); + public void token_type() => Get("token_type").Value().Should().Be(_sut.TokenType); [Fact] - public void expires_in() => _json["expires_in"].Value().Should().Be(_sut.ExpiresIn); + public void expires_in() => Get("expires_in").Value().Should().Be(_sut.ExpiresIn); [Fact] - public void refresh_token() => _json["refresh_token"].Value().Should().Be(_sut.RefreshToken); + public void refresh_token() => Get("refresh_token").Value().Should().Be(_sut.RefreshToken); [Fact] - public void created_at() => _json["created_at"].Value().Should().Be(_sut.CreatedAt); + public void created_at() => Get("created_at").Value().Should().Be(_sut.CreatedAt); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_serializing_and_deserializing_AccessTokenResponse : FixtureContext @@ -58,7 +60,7 @@ public When_serializing_and_deserializing_AccessTokenResponse(ITestOutputHelper output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject(); + _actual = json.ToObject() ?? throw new InvalidOperationException(); } [Fact] @@ -73,25 +75,27 @@ public class When_deserializing_AccessTokenResponse_Should_deserialize public When_deserializing_AccessTokenResponse_Should_deserialize(ITestOutputHelper output) { _json = SampleJson.AccessTokenResponse; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] - public void access_token() => _sut.AccessToken.Should().Be(_json["access_token"].Value()); + public void access_token() => _sut.AccessToken.Should().Be(Get("access_token").Value()); [Fact] - public void token_type() => _sut.TokenType.Should().Be(_json["token_type"].Value()); + public void token_type() => _sut.TokenType.Should().Be(Get("token_type").Value()); [Fact] - public void expires_in() => _sut.ExpiresIn.Should().Be(_json["expires_in"].Value()); + public void expires_in() => _sut.ExpiresIn.Should().Be(Get("expires_in").Value()); [Fact] - public void refresh_token() => _sut.RefreshToken.Should().Be(_json["refresh_token"].Value()); + public void refresh_token() => _sut.RefreshToken.Should().Be(Get("refresh_token").Value()); [Fact] - public void created_at() => _sut.CreatedAt.Should().Be(_json["created_at"].Value()); + public void created_at() => _sut.CreatedAt.Should().Be(Get("created_at").Value()); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_running_in_the_debugger_AccessTokenResponse_Should : DebuggerDisplayTestsBase @@ -128,7 +132,7 @@ public class AccessTokenResponse_Should_calculate public AccessTokenResponse_Should_calculate(ITestOutputHelper output) { JObject json = SampleJson.AccessTokenResponse; - _sut = json.ToObject(); + _sut = json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/ChargeStateTests.cs b/test/Tesla.NET.Tests/Models/Internal/ChargeStateTests.cs index 9a6a781..36c6880 100644 --- a/test/Tesla.NET.Tests/Models/Internal/ChargeStateTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/ChargeStateTests.cs @@ -32,167 +32,169 @@ public When_serializing_ChargeState_Should_serialize(ITestOutputHelper output) [Fact] public void charging_state() => - _json["charging_state"].Value().Should().Be(_sut.ChargingState); + Get("charging_state").Value().Should().Be(_sut.ChargingState); [Fact] public void fast_charger_type() => - _json["fast_charger_type"].Value().Should().Be(_sut.FastChargerType); + Get("fast_charger_type").Value().Should().Be(_sut.FastChargerType); [Fact] public void fast_charger_brand() => - _json["fast_charger_brand"].Value().Should().Be(_sut.FastChargerBrand); + Get("fast_charger_brand").Value().Should().Be(_sut.FastChargerBrand); [Fact] public void charge_limit_soc() => - _json["charge_limit_soc"].Value().Should().Be(_sut.ChargeLimitSoc); + Get("charge_limit_soc").Value().Should().Be(_sut.ChargeLimitSoc); [Fact] public void charge_limit_soc_std() => - _json["charge_limit_soc_std"].Value().Should().Be(_sut.ChargeLimitSocStd); + Get("charge_limit_soc_std").Value().Should().Be(_sut.ChargeLimitSocStd); [Fact] public void charge_limit_soc_min() => - _json["charge_limit_soc_min"].Value().Should().Be(_sut.ChargeLimitSocMin); + Get("charge_limit_soc_min").Value().Should().Be(_sut.ChargeLimitSocMin); [Fact] public void charge_limit_soc_max() => - _json["charge_limit_soc_max"].Value().Should().Be(_sut.ChargeLimitSocMax); + Get("charge_limit_soc_max").Value().Should().Be(_sut.ChargeLimitSocMax); [Fact] public void charge_to_max_range() => - _json["charge_to_max_range"].Value().Should().Be(_sut.ChargeToMaxRange); + Get("charge_to_max_range").Value().Should().Be(_sut.ChargeToMaxRange); [Fact] public void max_range_charge_counter() => - _json["max_range_charge_counter"].Value().Should().Be(_sut.MaxRangeChargeCounter); + Get("max_range_charge_counter").Value().Should().Be(_sut.MaxRangeChargeCounter); [Fact] public void fast_charger_present() => - _json["fast_charger_present"].Value().Should().Be(_sut.FastChargerPresent); + Get("fast_charger_present").Value().Should().Be(_sut.FastChargerPresent); [Fact] public void battery_range() => - _json["battery_range"].Value().Should().Be(_sut.BatteryRange); + Get("battery_range").Value().Should().Be(_sut.BatteryRange); [Fact] public void est_battery_range() => - _json["est_battery_range"].Value().Should().Be(_sut.EstBatteryRange); + Get("est_battery_range").Value().Should().Be(_sut.EstBatteryRange); [Fact] public void ideal_battery_range() => - _json["ideal_battery_range"].Value().Should().Be(_sut.IdealBatteryRange); + Get("ideal_battery_range").Value().Should().Be(_sut.IdealBatteryRange); [Fact] public void battery_level() => - _json["battery_level"].Value().Should().Be(_sut.BatteryLevel); + Get("battery_level").Value().Should().Be(_sut.BatteryLevel); [Fact] public void usable_battery_level() => - _json["usable_battery_level"].Value().Should().Be(_sut.UsableBatteryLevel); + Get("usable_battery_level").Value().Should().Be(_sut.UsableBatteryLevel); [Fact] public void charge_energy_added() => - _json["charge_energy_added"].Value().Should().Be(_sut.ChargeEnergyAdded); + Get("charge_energy_added").Value().Should().Be(_sut.ChargeEnergyAdded); [Fact] public void charge_miles_added_rated() => - _json["charge_miles_added_rated"].Value().Should().Be(_sut.ChargeMilesAddedRated); + Get("charge_miles_added_rated").Value().Should().Be(_sut.ChargeMilesAddedRated); [Fact] public void charge_miles_added_ideal() => - _json["charge_miles_added_ideal"].Value().Should().Be(_sut.ChargeMilesAddedIdeal); + Get("charge_miles_added_ideal").Value().Should().Be(_sut.ChargeMilesAddedIdeal); [Fact] public void charger_voltage() => - _json["charger_voltage"].Value().Should().Be(_sut.ChargerVoltage); + Get("charger_voltage").Value().Should().Be(_sut.ChargerVoltage); [Fact] public void charger_pilot_current() => - _json["charger_pilot_current"].Value().Should().Be(_sut.ChargerPilotCurrent); + Get("charger_pilot_current").Value().Should().Be(_sut.ChargerPilotCurrent); [Fact] public void charger_actual_current() => - _json["charger_actual_current"].Value().Should().Be(_sut.ChargerActualCurrent); + Get("charger_actual_current").Value().Should().Be(_sut.ChargerActualCurrent); [Fact] public void charger_power() => - _json["charger_power"].Value().Should().Be(_sut.ChargerPower); + Get("charger_power").Value().Should().Be(_sut.ChargerPower); [Fact] public void time_to_full_charge() => - _json["time_to_full_charge"].Value().Should().Be(_sut.TimeToFullCharge); + Get("time_to_full_charge").Value().Should().Be(_sut.TimeToFullCharge); [Fact] public void trip_charging() => - _json["trip_charging"].Value().Should().Be(_sut.TripCharging); + Get("trip_charging").Value().Should().Be(_sut.TripCharging); [Fact] public void charge_rate() => - _json["charge_rate"].Value().Should().Be(_sut.ChargeRate); + Get("charge_rate").Value().Should().Be(_sut.ChargeRate); [Fact] public void charge_port_door_open() => - _json["charge_port_door_open"].Value().Should().Be(_sut.ChargePortDoorOpen); + Get("charge_port_door_open").Value().Should().Be(_sut.ChargePortDoorOpen); [Fact] public void conn_charge_cable() => - _json["conn_charge_cable"].Value().Should().Be(_sut.ConnChargeCable); + Get("conn_charge_cable").Value().Should().Be(_sut.ConnChargeCable); [Fact] public void scheduled_charging_start_time() => - _json["scheduled_charging_start_time"].Value().Should().Be(_sut.ScheduledChargingStartTime); + Get("scheduled_charging_start_time").Value().Should().Be(_sut.ScheduledChargingStartTime); [Fact] public void scheduled_charging_pending() => - _json["scheduled_charging_pending"].Value().Should().Be(_sut.ScheduledChargingPending); + Get("scheduled_charging_pending").Value().Should().Be(_sut.ScheduledChargingPending); [Fact] public void user_charge_enable_request() => - _json["user_charge_enable_request"].Value().Should().Be(_sut.UserChargeEnableRequest); + Get("user_charge_enable_request").Value().Should().Be(_sut.UserChargeEnableRequest); [Fact] public void charge_enable_request() => - _json["charge_enable_request"].Value().Should().Be(_sut.ChargeEnableRequest); + Get("charge_enable_request").Value().Should().Be(_sut.ChargeEnableRequest); [Fact] public void charger_phases() => - _json["charger_phases"].Value().Should().Be(_sut.ChargerPhases); + Get("charger_phases").Value().Should().Be(_sut.ChargerPhases); [Fact] public void charge_port_latch() => - _json["charge_port_latch"].Value().Should().Be(_sut.ChargePortLatch); + Get("charge_port_latch").Value().Should().Be(_sut.ChargePortLatch); [Fact] public void charge_current_request() => - _json["charge_current_request"].Value().Should().Be(_sut.ChargeCurrentRequest); + Get("charge_current_request").Value().Should().Be(_sut.ChargeCurrentRequest); [Fact] public void charge_current_request_max() => - _json["charge_current_request_max"].Value().Should().Be(_sut.ChargeCurrentRequestMax); + Get("charge_current_request_max").Value().Should().Be(_sut.ChargeCurrentRequestMax); [Fact] public void managed_charging_active() => - _json["managed_charging_active"].Value().Should().Be(_sut.ManagedChargingActive); + Get("managed_charging_active").Value().Should().Be(_sut.ManagedChargingActive); [Fact] public void managed_charging_user_canceled() => - _json["managed_charging_user_canceled"].Value().Should().Be(_sut.ManagedChargingUserCanceled); + Get("managed_charging_user_canceled").Value().Should().Be(_sut.ManagedChargingUserCanceled); [Fact] public void managed_charging_start_time() => - _json["managed_charging_start_time"].Value().Should().Be(_sut.ManagedChargingStartTime); + Get("managed_charging_start_time").Value().Should().Be(_sut.ManagedChargingStartTime); [Fact] public void battery_heater_on() => - _json["battery_heater_on"].Value().Should().Be(_sut.BatteryHeaterOn); + Get("battery_heater_on").Value().Should().Be(_sut.BatteryHeaterOn); [Fact] public void not_enough_power_to_heat() => - _json["not_enough_power_to_heat"].Value().Should().Be(_sut.NotEnoughPowerToHeat); + Get("not_enough_power_to_heat").Value().Should().Be(_sut.NotEnoughPowerToHeat); [Fact] public void timestamp() => - _json["timestamp"].Value().Should().Be(_sut.Timestamp); + Get("timestamp").Value().Should().Be(_sut.Timestamp); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_serializing_and_deserializing_ChargeState : FixtureContext @@ -208,7 +210,7 @@ public When_serializing_and_deserializing_ChargeState(ITestOutputHelper output) output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject(); + _actual = json.ToObject() ?? throw new InvalidOperationException(); } [Fact] @@ -224,174 +226,176 @@ public When_deserializing_ChargeState_Should_deserialize(ITestOutputHelper outpu : base(output) { _json = SampleJson.ChargeState; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] public void charging_state() => - _sut.ChargingState.Should().Be(_json["charging_state"].Value()); + _sut.ChargingState.Should().Be(Get("charging_state").Value()); [Fact] public void fast_charger_type() => - _sut.FastChargerType.Should().Be(_json["fast_charger_type"].Value()); + _sut.FastChargerType.Should().Be(Get("fast_charger_type").Value()); [Fact] public void fast_charger_brand() => - _sut.FastChargerBrand.Should().Be(_json["fast_charger_brand"].Value()); + _sut.FastChargerBrand.Should().Be(Get("fast_charger_brand").Value()); [Fact] public void charge_limit_soc() => - _sut.ChargeLimitSoc.Should().Be(_json["charge_limit_soc"].Value()); + _sut.ChargeLimitSoc.Should().Be(Get("charge_limit_soc").Value()); [Fact] public void charge_limit_soc_std() => - _sut.ChargeLimitSocStd.Should().Be(_json["charge_limit_soc_std"].Value()); + _sut.ChargeLimitSocStd.Should().Be(Get("charge_limit_soc_std").Value()); [Fact] public void charge_limit_soc_min() => - _sut.ChargeLimitSocMin.Should().Be(_json["charge_limit_soc_min"].Value()); + _sut.ChargeLimitSocMin.Should().Be(Get("charge_limit_soc_min").Value()); [Fact] public void charge_limit_soc_max() => - _sut.ChargeLimitSocMax.Should().Be(_json["charge_limit_soc_max"].Value()); + _sut.ChargeLimitSocMax.Should().Be(Get("charge_limit_soc_max").Value()); [Fact] public void charge_to_max_range() => - _sut.ChargeToMaxRange.Should().Be(_json["charge_to_max_range"].Value()); + _sut.ChargeToMaxRange.Should().Be(Get("charge_to_max_range").Value()); [Fact] public void max_range_charge_counter() => - _sut.MaxRangeChargeCounter.Should().Be(_json["max_range_charge_counter"].Value()); + _sut.MaxRangeChargeCounter.Should().Be(Get("max_range_charge_counter").Value()); [Fact] public void fast_charger_present() => - _sut.FastChargerPresent.Should().Be(_json["fast_charger_present"].Value()); + _sut.FastChargerPresent.Should().Be(Get("fast_charger_present").Value()); [Fact] public void battery_range() => - _sut.BatteryRange.Should().Be(_json["battery_range"].Value()); + _sut.BatteryRange.Should().Be(Get("battery_range").Value()); [Fact] public void est_battery_range() => - _sut.EstBatteryRange.Should().Be(_json["est_battery_range"].Value()); + _sut.EstBatteryRange.Should().Be(Get("est_battery_range").Value()); [Fact] public void ideal_battery_range() => - _sut.IdealBatteryRange.Should().Be(_json["ideal_battery_range"].Value()); + _sut.IdealBatteryRange.Should().Be(Get("ideal_battery_range").Value()); [Fact] public void battery_level() => - _sut.BatteryLevel.Should().Be(_json["battery_level"].Value()); + _sut.BatteryLevel.Should().Be(Get("battery_level").Value()); [Fact] public void usable_battery_level() => - _sut.UsableBatteryLevel.Should().Be(_json["usable_battery_level"].Value()); + _sut.UsableBatteryLevel.Should().Be(Get("usable_battery_level").Value()); [Fact] public void charge_energy_added() => - _sut.ChargeEnergyAdded.Should().Be(_json["charge_energy_added"].Value()); + _sut.ChargeEnergyAdded.Should().Be(Get("charge_energy_added").Value()); [Fact] public void charge_miles_added_rated() => - _sut.ChargeMilesAddedRated.Should().Be(_json["charge_miles_added_rated"].Value()); + _sut.ChargeMilesAddedRated.Should().Be(Get("charge_miles_added_rated").Value()); [Fact] public void charge_miles_added_ideal() => - _sut.ChargeMilesAddedIdeal.Should().Be(_json["charge_miles_added_ideal"].Value()); + _sut.ChargeMilesAddedIdeal.Should().Be(Get("charge_miles_added_ideal").Value()); [Fact] public void charger_voltage() => - _sut.ChargerVoltage.Should().Be(_json["charger_voltage"].Value()); + _sut.ChargerVoltage.Should().Be(Get("charger_voltage").Value()); [Fact] public void charger_pilot_current() => - _sut.ChargerPilotCurrent.Should().Be(_json["charger_pilot_current"].Value()); + _sut.ChargerPilotCurrent.Should().Be(Get("charger_pilot_current").Value()); [Fact] public void charger_actual_current() => - _sut.ChargerActualCurrent.Should().Be(_json["charger_actual_current"].Value()); + _sut.ChargerActualCurrent.Should().Be(Get("charger_actual_current").Value()); [Fact] public void charger_power() => - _sut.ChargerPower.Should().Be(_json["charger_power"].Value()); + _sut.ChargerPower.Should().Be(Get("charger_power").Value()); [Fact] public void time_to_full_charge() => - _sut.TimeToFullCharge.Should().Be(_json["time_to_full_charge"].Value()); + _sut.TimeToFullCharge.Should().Be(Get("time_to_full_charge").Value()); [Fact] public void trip_charging() => - _sut.TripCharging.Should().Be(_json["trip_charging"].Value()); + _sut.TripCharging.Should().Be(Get("trip_charging").Value()); [Fact] public void charge_rate() => - _sut.ChargeRate.Should().Be(_json["charge_rate"].Value()); + _sut.ChargeRate.Should().Be(Get("charge_rate").Value()); [Fact] public void charge_port_door_open() => - _sut.ChargePortDoorOpen.Should().Be(_json["charge_port_door_open"].Value()); + _sut.ChargePortDoorOpen.Should().Be(Get("charge_port_door_open").Value()); [Fact] public void conn_charge_cable() => - _sut.ConnChargeCable.Should().Be(_json["conn_charge_cable"].Value()); + _sut.ConnChargeCable.Should().Be(Get("conn_charge_cable").Value()); [Fact] public void scheduled_charging_start_time() => - _sut.ScheduledChargingStartTime.Should().Be(_json["scheduled_charging_start_time"].Value()); + _sut.ScheduledChargingStartTime.Should().Be(Get("scheduled_charging_start_time").Value()); [Fact] public void scheduled_charging_pending() => - _sut.ScheduledChargingPending.Should().Be(_json["scheduled_charging_pending"].Value()); + _sut.ScheduledChargingPending.Should().Be(Get("scheduled_charging_pending").Value()); [Fact] public void user_charge_enable_request() => - _sut.UserChargeEnableRequest.Should().Be(_json["user_charge_enable_request"].Value()); + _sut.UserChargeEnableRequest.Should().Be(Get("user_charge_enable_request").Value()); [Fact] public void charge_enable_request() => - _sut.ChargeEnableRequest.Should().Be(_json["charge_enable_request"].Value()); + _sut.ChargeEnableRequest.Should().Be(Get("charge_enable_request").Value()); [Fact] public void charger_phases() => - _sut.ChargerPhases.Should().Be(_json["charger_phases"].Value()); + _sut.ChargerPhases.Should().Be(Get("charger_phases").Value()); [Fact] public void charge_port_latch() => - _sut.ChargePortLatch.Should().Be(_json["charge_port_latch"].Value()); + _sut.ChargePortLatch.Should().Be(Get("charge_port_latch").Value()); [Fact] public void charge_current_request() => - _sut.ChargeCurrentRequest.Should().Be(_json["charge_current_request"].Value()); + _sut.ChargeCurrentRequest.Should().Be(Get("charge_current_request").Value()); [Fact] public void charge_current_request_max() => - _sut.ChargeCurrentRequestMax.Should().Be(_json["charge_current_request_max"].Value()); + _sut.ChargeCurrentRequestMax.Should().Be(Get("charge_current_request_max").Value()); [Fact] public void managed_charging_active() => - _sut.ManagedChargingActive.Should().Be(_json["managed_charging_active"].Value()); + _sut.ManagedChargingActive.Should().Be(Get("managed_charging_active").Value()); [Fact] public void managed_charging_user_canceled() => - _sut.ManagedChargingUserCanceled.Should().Be(_json["managed_charging_user_canceled"].Value()); + _sut.ManagedChargingUserCanceled.Should().Be(Get("managed_charging_user_canceled").Value()); [Fact] public void managed_charging_start_time() => - _sut.ManagedChargingStartTime.Should().Be(_json["managed_charging_start_time"].Value()); + _sut.ManagedChargingStartTime.Should().Be(Get("managed_charging_start_time").Value()); [Fact] public void battery_heater_on() => - _sut.BatteryHeaterOn.Should().Be(_json["battery_heater_on"].Value()); + _sut.BatteryHeaterOn.Should().Be(Get("battery_heater_on").Value()); [Fact] public void not_enough_power_to_heat() => - _sut.NotEnoughPowerToHeat.Should().Be(_json["not_enough_power_to_heat"].Value()); + _sut.NotEnoughPowerToHeat.Should().Be(Get("not_enough_power_to_heat").Value()); [Fact] public void timestamp() => - _sut.Timestamp.Should().Be(_json["timestamp"].Value()); + _sut.Timestamp.Should().Be(Get("timestamp").Value()); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_deserializing_ChargeState_with_minimal_data_Should_default @@ -402,7 +406,7 @@ public class When_deserializing_ChargeState_with_minimal_data_Should_default public When_deserializing_ChargeState_with_minimal_data_Should_default(ITestOutputHelper output) { _json = SampleJson.ChargeStateMinimal; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } @@ -534,7 +538,9 @@ public When_deserializing_ChargeState_with_minimal_data_Should_default(ITestOutp public void not_enough_power_to_heat() => _sut.NotEnoughPowerToHeat.Should().BeNull(); [Fact] - public void timestamp() => _sut.Timestamp.Should().Be(_json["timestamp"].Value()); + public void timestamp() => _sut.Timestamp.Should().Be(Get("timestamp").Value()); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_running_in_the_debugger_ChargeState_Should : DebuggerDisplayTestsBase @@ -578,7 +584,7 @@ public class ChargeState_Should_calculate public ChargeState_Should_calculate(ITestOutputHelper output) { JObject json = SampleJson.ChargeState; - _sut = json.ToObject(); + _sut = json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/DriveStateTests.cs b/test/Tesla.NET.Tests/Models/Internal/DriveStateTests.cs index 6456178..25b32e6 100644 --- a/test/Tesla.NET.Tests/Models/Internal/DriveStateTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/DriveStateTests.cs @@ -31,28 +31,30 @@ public When_serializing_DriveState_Should_serialize(ITestOutputHelper output) public void eight_properties() => _json.Count.Should().Be(8); [Fact] - public void shift_state() => _json["shift_state"].Value().Should().Be(_sut.ShiftState); + public void shift_state() => Get("shift_state").Value().Should().Be(_sut.ShiftState); [Fact] - public void speed() => _json["speed"].Value().Should().Be(_sut.Speed); + public void speed() => Get("speed").Value().Should().Be(_sut.Speed); [Fact] - public void power() => _json["power"].Value().Should().Be(_sut.Power); + public void power() => Get("power").Value().Should().Be(_sut.Power); [Fact] - public void latitude() => _json["latitude"].Value().Should().Be(_sut.Latitude); + public void latitude() => Get("latitude").Value().Should().Be(_sut.Latitude); [Fact] - public void longitude() => _json["longitude"].Value().Should().Be(_sut.Longitude); + public void longitude() => Get("longitude").Value().Should().Be(_sut.Longitude); [Fact] - public void heading() => _json["heading"].Value().Should().Be(_sut.Heading); + public void heading() => Get("heading").Value().Should().Be(_sut.Heading); [Fact] - public void gps_as_of() => _json["gps_as_of"].Value().Should().Be(_sut.GpsAsOf); + public void gps_as_of() => Get("gps_as_of").Value().Should().Be(_sut.GpsAsOf); [Fact] - public void timestamp() => _json["timestamp"].Value().Should().Be(_sut.Timestamp); + public void timestamp() => Get("timestamp").Value().Should().Be(_sut.Timestamp); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_serializing_and_deserializing_DriveState : FixtureContext @@ -68,7 +70,7 @@ public When_serializing_and_deserializing_DriveState(ITestOutputHelper output) output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject(); + _actual = json.ToObject() ?? throw new InvalidOperationException(); } [Fact] @@ -84,34 +86,36 @@ public When_deserializing_DriveState_Should_deserialize(ITestOutputHelper output : base(output) { _json = SampleJson.DriveState; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] - public void shift_state() => _sut.ShiftState.Should().Be(_json["shift_state"].Value()); + public void shift_state() => _sut.ShiftState.Should().Be(Get("shift_state").Value()); [Fact] - public void speed() => _sut.Speed.Should().Be(_json["speed"].Value()); + public void speed() => _sut.Speed.Should().Be(Get("speed").Value()); [Fact] - public void power() => _sut.Power.Should().Be(_json["power"].Value()); + public void power() => _sut.Power.Should().Be(Get("power").Value()); [Fact] - public void latitude() => _sut.Latitude.Should().Be(_json["latitude"].Value()); + public void latitude() => _sut.Latitude.Should().Be(Get("latitude").Value()); [Fact] - public void longitude() => _sut.Longitude.Should().Be(_json["longitude"].Value()); + public void longitude() => _sut.Longitude.Should().Be(Get("longitude").Value()); [Fact] - public void heading() => _sut.Heading.Should().Be(_json["heading"].Value()); + public void heading() => _sut.Heading.Should().Be(Get("heading").Value()); [Fact] - public void gps_as_of() => _sut.GpsAsOf.Should().Be(_json["gps_as_of"].Value()); + public void gps_as_of() => _sut.GpsAsOf.Should().Be(Get("gps_as_of").Value()); [Fact] - public void timestamp() => _sut.Timestamp.Should().Be(_json["timestamp"].Value()); + public void timestamp() => _sut.Timestamp.Should().Be(Get("timestamp").Value()); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_deserializing_DriveState_with_minimal_data_Should_default @@ -122,7 +126,7 @@ public class When_deserializing_DriveState_with_minimal_data_Should_default public When_deserializing_DriveState_with_minimal_data_Should_default(ITestOutputHelper output) { _json = SampleJson.DriveStateMinimal; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } @@ -134,22 +138,22 @@ public When_deserializing_DriveState_with_minimal_data_Should_default(ITestOutpu public void speed() => _sut.Speed.Should().NotBeNull().And.BeEmpty(); [Fact] - public void power() => _sut.Power.Should().Be(default(long)); + public void power() => _sut.Power.Should().Be(default); [Fact] - public void latitude() => _sut.Latitude.Should().Be(default(double)); + public void latitude() => _sut.Latitude.Should().Be(default); [Fact] - public void longitude() => _sut.Longitude.Should().Be(default(double)); + public void longitude() => _sut.Longitude.Should().Be(default); [Fact] - public void heading() => _sut.Heading.Should().Be(default(long)); + public void heading() => _sut.Heading.Should().Be(default); [Fact] - public void gps_as_of() => _sut.GpsAsOf.Should().Be(default(long)); + public void gps_as_of() => _sut.GpsAsOf.Should().Be(default); [Fact] - public void timestamp() => _sut.Timestamp.Should().Be(default(long)); + public void timestamp() => _sut.Timestamp.Should().Be(default); } public class When_running_in_the_debugger_DriveState_Should : DebuggerDisplayTestsBase @@ -192,7 +196,7 @@ public class DriveState_Should_calculate public DriveState_Should_calculate(ITestOutputHelper output) { JObject json = SampleJson.DriveState; - _sut = json.ToObject(); + _sut = json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/GetChargeStateResponseTests.cs b/test/Tesla.NET.Tests/Models/Internal/GetChargeStateResponseTests.cs index c402576..7c2971a 100644 --- a/test/Tesla.NET.Tests/Models/Internal/GetChargeStateResponseTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/GetChargeStateResponseTests.cs @@ -43,7 +43,7 @@ public When_serializing_and_deserializing_GetChargeStateResponse(ITestOutputHelp output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject>(); + _actual = json.ToObject>() ?? throw new InvalidOperationException(); } [Fact] @@ -60,8 +60,8 @@ public When_deserializing_GetChargeStateResponse_Should_deserialize(ITestOutputH : base(output) { _json = SampleJson.GetChargeStateResponse; - _sut = _json.ToObject>(); - _expectedResponse = SampleJson.ChargeState.ToObject(); + _sut = _json.ToObject>() ?? throw new InvalidOperationException(); + _expectedResponse = SampleJson.ChargeState.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/GetDriveStateResponseTests.cs b/test/Tesla.NET.Tests/Models/Internal/GetDriveStateResponseTests.cs index 69c8913..7e4c46b 100644 --- a/test/Tesla.NET.Tests/Models/Internal/GetDriveStateResponseTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/GetDriveStateResponseTests.cs @@ -43,7 +43,7 @@ public When_serializing_and_deserializing_GetDriveStateResponse(ITestOutputHelpe output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject>(); + _actual = json.ToObject>() ?? throw new InvalidOperationException(); } [Fact] @@ -60,8 +60,8 @@ public When_deserializing_GetDriveStateResponse_Should_deserialize(ITestOutputHe : base(output) { _json = SampleJson.GetDriveStateResponse; - _sut = _json.ToObject>(); - _expectedResponse = SampleJson.DriveState.ToObject(); + _sut = _json.ToObject>() ?? throw new InvalidOperationException(); + _expectedResponse = SampleJson.DriveState.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/GetVehicleStateResponseTests.cs b/test/Tesla.NET.Tests/Models/Internal/GetVehicleStateResponseTests.cs index 968ed71..89d67f5 100644 --- a/test/Tesla.NET.Tests/Models/Internal/GetVehicleStateResponseTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/GetVehicleStateResponseTests.cs @@ -43,7 +43,7 @@ public When_serializing_and_deserializing_GetVehicleStateResponse(ITestOutputHel output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject>(); + _actual = json.ToObject>() ?? throw new InvalidOperationException(); } [Fact] @@ -60,8 +60,9 @@ public When_deserializing_GetVehicleStateResponse_Should_deserialize(ITestOutput : base(output) { _json = SampleJson.GetVehicleStateResponse; - _sut = _json.ToObject>(); - _expectedResponse = SampleJson.VehicleState.ToObject(); + _sut = _json.ToObject>() ?? throw new InvalidOperationException(); + _expectedResponse = SampleJson.VehicleState.ToObject() + ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/GetVehiclesResponseTests.cs b/test/Tesla.NET.Tests/Models/Internal/GetVehiclesResponseTests.cs index 8afdd86..b7d0711 100644 --- a/test/Tesla.NET.Tests/Models/Internal/GetVehiclesResponseTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/GetVehiclesResponseTests.cs @@ -43,7 +43,8 @@ public When_serializing_and_deserializing_GetVehiclesResponse(ITestOutputHelper output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject>>(); + _actual = json.ToObject>>() + ?? throw new InvalidOperationException(); } [Fact] @@ -60,16 +61,17 @@ public When_deserializing_GetVehiclesResponse_Should_deserialize(ITestOutputHelp : base(output) { _json = SampleJson.GetVehiclesResponse; - _sut = _json.ToObject>>(); + _sut = _json.ToObject>>() + ?? throw new InvalidOperationException(); _expectedResponse = new[] { - SampleJson.Vehicle.ToObject(), + SampleJson.Vehicle.ToObject() ?? throw new InvalidOperationException(), }; output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] - public void response() =>_sut.Response.Should().BeEquivalentTo(_expectedResponse, WithStrictOrdering); + public void response() => _sut.Response.Should().BeEquivalentTo(_expectedResponse, WithStrictOrdering); } } diff --git a/test/Tesla.NET.Tests/Models/Internal/MessageResponseTests.cs b/test/Tesla.NET.Tests/Models/Internal/MessageResponseTests.cs index 3f383c1..ae49484 100644 --- a/test/Tesla.NET.Tests/Models/Internal/MessageResponseTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/MessageResponseTests.cs @@ -46,10 +46,12 @@ public When_getting_the_raw_JSON_MessageResponse_Should(ITestOutputHelper output _rawJson = SampleJson.GetDriveStateResponse; _rawJson["randomValue1"] = Fixture.Create("randomValue1"); _rawJson["randomValue2"] = JObject.FromObject(new { fakeId = Guid.NewGuid() }); - _rawJson["response"]["randomValue3"] = Fixture.Create("randomValue3"); + JToken response = _rawJson["response"] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("randomValue3"); _rawJsonString = _rawJson.ToString(Formatting.Indented); - ResponseDataWrapper data = _rawJson.ToObject>(); + ResponseDataWrapper data = + _rawJson.ToObject>() ?? throw new InvalidOperationException(); _sut = new MessageResponse>(HttpStatusCode.OK, _rawJson, data); @@ -60,7 +62,7 @@ public When_getting_the_raw_JSON_MessageResponse_Should(ITestOutputHelper output public void return_a_deep_clone_of_the_raw_JSON() { // Act - JObject clone = _sut.RawJson; + JObject clone = _sut.RawJson ?? throw new InvalidOperationException(); _output.WriteLine("Cloned JSON:" + Environment.NewLine + clone); @@ -73,8 +75,9 @@ public void return_a_deep_clone_of_the_raw_JSON() public void not_change_the_original_JSON() { // Act - JObject clone = _sut.RawJson; - clone["response"]["randomValue3"] = Fixture.Create("updatedRandomValue3"); + JObject clone = _sut.RawJson ?? throw new InvalidOperationException(); + JToken response = clone["response"] ?? throw new InvalidOperationException("response is null."); + response["randomValue3"] = Fixture.Create("updatedRandomValue3"); _output.WriteLine("Modified JSON:" + Environment.NewLine + clone); @@ -87,7 +90,7 @@ public void not_change_the_original_JSON() public void return_a_new_clone_every_time() { // Act - JObject clone1 = _sut.RawJson; + JObject clone1 = _sut.RawJson ?? throw new InvalidOperationException(); JObject clone2 = _sut.RawJson; // Assert diff --git a/test/Tesla.NET.Tests/Models/Internal/VehicleStateTests.cs b/test/Tesla.NET.Tests/Models/Internal/VehicleStateTests.cs index 81a0797..4ec918c 100644 --- a/test/Tesla.NET.Tests/Models/Internal/VehicleStateTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/VehicleStateTests.cs @@ -30,93 +30,95 @@ public When_serializing_VehicleState_Should_serialize(ITestOutputHelper output) public void twenty_seven_properties() => _json.Count.Should().Be(27); [Fact] - public void api_version() => _json["api_version"].Value().Should().Be(_sut.ApiVersion); + public void api_version() => Get("api_version").Value().Should().Be(_sut.ApiVersion); [Fact] - public void autopark_state() => _json["autopark_state"].Value().Should().Be(_sut.AutoparkState); + public void autopark_state() => Get("autopark_state").Value().Should().Be(_sut.AutoparkState); [Fact] public void autopark_state_v2() - => _json["autopark_state_v2"].Value().Should().Be(_sut.AutoparkStateV2); + => Get("autopark_state_v2").Value().Should().Be(_sut.AutoparkStateV2); [Fact] - public void autopark_style() => _json["autopark_style"].Value().Should().Be(_sut.AutoparkStyle); + public void autopark_style() => Get("autopark_style").Value().Should().Be(_sut.AutoparkStyle); [Fact] public void calendar_supported() - => _json["calendar_supported"].Value().Should().Be(_sut.CalendarSupported); + => Get("calendar_supported").Value().Should().Be(_sut.CalendarSupported); [Fact] - public void car_version() => _json["car_version"].Value().Should().Be(_sut.CarVersion); + public void car_version() => Get("car_version").Value().Should().Be(_sut.CarVersion); [Fact] public void center_display_state() - => _json["center_display_state"].Value().Should().Be(_sut.CenterDisplayState); + => Get("center_display_state").Value().Should().Be(_sut.CenterDisplayState); [Fact] - public void df() => _json["df"].Value().Should().Be(_sut.Df); + public void df() => Get("df").Value().Should().Be(_sut.Df); [Fact] - public void dr() => _json["dr"].Value().Should().Be(_sut.Dr); + public void dr() => Get("dr").Value().Should().Be(_sut.Dr); [Fact] - public void ft() => _json["ft"].Value().Should().Be(_sut.Ft); + public void ft() => Get("ft").Value().Should().Be(_sut.Ft); [Fact] - public void homelink_nearby() => _json["homelink_nearby"].Value().Should().Be(_sut.HomelinkNearby); + public void homelink_nearby() => Get("homelink_nearby").Value().Should().Be(_sut.HomelinkNearby); [Fact] public void last_autopark_error() - => _json["last_autopark_error"].Value().Should().Be(_sut.LastAutoparkError); + => Get("last_autopark_error").Value().Should().Be(_sut.LastAutoparkError); [Fact] - public void locked() => _json["locked"].Value().Should().Be(_sut.Locked); + public void locked() => Get("locked").Value().Should().Be(_sut.Locked); [Fact] public void notifications_supported() - => _json["notifications_supported"].Value().Should().Be(_sut.NotificationsSupported); + => Get("notifications_supported").Value().Should().Be(_sut.NotificationsSupported); [Fact] - public void odometer() => _json["odometer"].Value().Should().Be(_sut.Odometer); + public void odometer() => Get("odometer").Value().Should().Be(_sut.Odometer); [Fact] public void parsed_calendar_supported() - => _json["parsed_calendar_supported"].Value().Should().Be(_sut.ParsedCalendarSupported); + => Get("parsed_calendar_supported").Value().Should().Be(_sut.ParsedCalendarSupported); [Fact] - public void pf() => _json["pf"].Value().Should().Be(_sut.Pf); + public void pf() => Get("pf").Value().Should().Be(_sut.Pf); [Fact] - public void pr() => _json["pr"].Value().Should().Be(_sut.Pr); + public void pr() => Get("pr").Value().Should().Be(_sut.Pr); [Fact] - public void remote_start() => _json["remote_start"].Value().Should().Be(_sut.RemoteStart); + public void remote_start() => Get("remote_start").Value().Should().Be(_sut.RemoteStart); [Fact] public void remote_start_supported() - => _json["remote_start_supported"].Value().Should().Be(_sut.RemoteStartSupported); + => Get("remote_start_supported").Value().Should().Be(_sut.RemoteStartSupported); [Fact] - public void rt() => _json["rt"].Value().Should().Be(_sut.Rt); + public void rt() => Get("rt").Value().Should().Be(_sut.Rt); [Fact] public void sun_roof_percent_open() - => _json["sun_roof_percent_open"].Value().Should().Be(_sut.SunRoofPercentOpen); + => Get("sun_roof_percent_open").Value().Should().Be(_sut.SunRoofPercentOpen); [Fact] - public void sun_roof_state() => _json["sun_roof_state"].Value().Should().Be(_sut.SunRoofState); + public void sun_roof_state() => Get("sun_roof_state").Value().Should().Be(_sut.SunRoofState); [Fact] - public void timestamp() => _json["timestamp"].Value().Should().Be(_sut.Timestamp); + public void timestamp() => Get("timestamp").Value().Should().Be(_sut.Timestamp); [Fact] - public void valet_mode() => _json["valet_mode"].Value().Should().Be(_sut.ValetMode); + public void valet_mode() => Get("valet_mode").Value().Should().Be(_sut.ValetMode); [Fact] - public void valet_pin_needed() => _json["valet_pin_needed"].Value().Should().Be(_sut.ValetPinNeeded); + public void valet_pin_needed() => Get("valet_pin_needed").Value().Should().Be(_sut.ValetPinNeeded); [Fact] - public void vehicle_name() => _json["vehicle_name"].Value().Should().Be(_sut.VehicleName); + public void vehicle_name() => Get("vehicle_name").Value().Should().Be(_sut.VehicleName); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_serializing_and_deserializing_VehicleState : FixtureContext @@ -132,7 +134,7 @@ public When_serializing_and_deserializing_VehicleState(ITestOutputHelper output) output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject(); + _actual = json.ToObject() ?? throw new InvalidOperationException(); } [Fact] @@ -148,99 +150,101 @@ public When_deserializing_VehicleState_Should_deserialize(ITestOutputHelper outp : base(output) { _json = SampleJson.VehicleState; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] - public void api_version() => _sut.ApiVersion.Should().Be(_json["api_version"].Value()); + public void api_version() => _sut.ApiVersion.Should().Be(Get("api_version").Value()); [Fact] - public void autopark_state() => _sut.AutoparkState.Should().Be(_json["autopark_state"].Value()); + public void autopark_state() => _sut.AutoparkState.Should().Be(Get("autopark_state").Value()); [Fact] public void autopark_state_v2() - => _sut.AutoparkStateV2.Should().Be(_json["autopark_state_v2"].Value()); + => _sut.AutoparkStateV2.Should().Be(Get("autopark_state_v2").Value()); [Fact] - public void autopark_style() => _sut.AutoparkStyle.Should().Be(_json["autopark_style"].Value()); + public void autopark_style() => _sut.AutoparkStyle.Should().Be(Get("autopark_style").Value()); [Fact] public void calendar_supported() - => _sut.CalendarSupported.Should().Be(_json["calendar_supported"].Value()); + => _sut.CalendarSupported.Should().Be(Get("calendar_supported").Value()); [Fact] - public void car_version() => _sut.CarVersion.Should().Be(_json["car_version"].Value()); + public void car_version() => _sut.CarVersion.Should().Be(Get("car_version").Value()); [Fact] public void center_display_state() - => _sut.CenterDisplayState.Should().Be(_json["center_display_state"].Value()); + => _sut.CenterDisplayState.Should().Be(Get("center_display_state").Value()); [Fact] - public void df() => _sut.Df.Should().Be(_json["df"].Value()); + public void df() => _sut.Df.Should().Be(Get("df").Value()); [Fact] - public void dr() => _sut.Dr.Should().Be(_json["dr"].Value()); + public void dr() => _sut.Dr.Should().Be(Get("dr").Value()); [Fact] - public void ft() => _sut.Ft.Should().Be(_json["ft"].Value()); + public void ft() => _sut.Ft.Should().Be(Get("ft").Value()); [Fact] - public void homelink_nearby() => _sut.HomelinkNearby.Should().Be(_json["homelink_nearby"].Value()); + public void homelink_nearby() => _sut.HomelinkNearby.Should().Be(Get("homelink_nearby").Value()); [Fact] public void last_autopark_error() - => _sut.LastAutoparkError.Should().Be(_json["last_autopark_error"].Value()); + => _sut.LastAutoparkError.Should().Be(Get("last_autopark_error").Value()); [Fact] - public void locked() => _sut.Locked.Should().Be(_json["locked"].Value()); + public void locked() => _sut.Locked.Should().Be(Get("locked").Value()); [Fact] public void notifications_supported() - => _sut.NotificationsSupported.Should().Be(_json["notifications_supported"].Value()); + => _sut.NotificationsSupported.Should().Be(Get("notifications_supported").Value()); [Fact] - public void odometer() => _sut.Odometer.Should().Be(_json["odometer"].Value()); + public void odometer() => _sut.Odometer.Should().Be(Get("odometer").Value()); [Fact] public void parsed_calendar_supported() - => _sut.ParsedCalendarSupported.Should().Be(_json["parsed_calendar_supported"].Value()); + => _sut.ParsedCalendarSupported.Should().Be(Get("parsed_calendar_supported").Value()); [Fact] - public void pf() => _sut.Pf.Should().Be(_json["pf"].Value()); + public void pf() => _sut.Pf.Should().Be(Get("pf").Value()); [Fact] - public void pr() => _sut.Pr.Should().Be(_json["pr"].Value()); + public void pr() => _sut.Pr.Should().Be(Get("pr").Value()); [Fact] - public void remote_start() => _sut.RemoteStart.Should().Be(_json["remote_start"].Value()); + public void remote_start() => _sut.RemoteStart.Should().Be(Get("remote_start").Value()); [Fact] public void remote_start_supported() - => _sut.RemoteStartSupported.Should().Be(_json["remote_start_supported"].Value()); + => _sut.RemoteStartSupported.Should().Be(Get("remote_start_supported").Value()); [Fact] - public void rt() => _sut.Rt.Should().Be(_json["rt"].Value()); + public void rt() => _sut.Rt.Should().Be(Get("rt").Value()); [Fact] public void sun_roof_percent_open() - => _sut.SunRoofPercentOpen.Should().Be(_json["sun_roof_percent_open"].Value()); + => _sut.SunRoofPercentOpen.Should().Be(Get("sun_roof_percent_open").Value()); [Fact] - public void sun_roof_state() => _sut.SunRoofState.Should().Be(_json["sun_roof_state"].Value()); + public void sun_roof_state() => _sut.SunRoofState.Should().Be(Get("sun_roof_state").Value()); [Fact] - public void timestamp() => _sut.Timestamp.Should().Be(_json["timestamp"].Value()); + public void timestamp() => _sut.Timestamp.Should().Be(Get("timestamp").Value()); [Fact] - public void valet_mode() => _sut.ValetMode.Should().Be(_json["valet_mode"].Value()); + public void valet_mode() => _sut.ValetMode.Should().Be(Get("valet_mode").Value()); [Fact] - public void valet_pin_needed() => _sut.ValetPinNeeded.Should().Be(_json["valet_pin_needed"].Value()); + public void valet_pin_needed() => _sut.ValetPinNeeded.Should().Be(Get("valet_pin_needed").Value()); [Fact] - public void vehicle_name() => _sut.VehicleName.Should().Be(_json["vehicle_name"].Value()); + public void vehicle_name() => _sut.VehicleName.Should().Be(Get("vehicle_name").Value()); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_deserializing_VehicleState_with_minimal_data_Should_default @@ -251,7 +255,7 @@ public class When_deserializing_VehicleState_with_minimal_data_Should_default public When_deserializing_VehicleState_with_minimal_data_Should_default(ITestOutputHelper output) { _json = SampleJson.VehicleStateMinimal; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } @@ -275,16 +279,16 @@ public When_deserializing_VehicleState_with_minimal_data_Should_default(ITestOut public void car_version() => _sut.CarVersion.Should().NotBeNull().And.BeEmpty(); [Fact] - public void center_display_state() => _sut.CenterDisplayState.Should().Be(default(long)); + public void center_display_state() => _sut.CenterDisplayState.Should().Be(default); [Fact] - public void df() => _sut.Df.Should().Be(default(long)); + public void df() => _sut.Df.Should().Be(default); [Fact] - public void dr() => _sut.Dr.Should().Be(default(long)); + public void dr() => _sut.Dr.Should().Be(default); [Fact] - public void ft() => _sut.Ft.Should().Be(default(long)); + public void ft() => _sut.Ft.Should().Be(default); [Fact] public void homelink_nearby() => _sut.HomelinkNearby.Should().BeFalse(); @@ -378,7 +382,7 @@ public class VehicleState_Should_calculate public VehicleState_Should_calculate(ITestOutputHelper output) { JObject json = SampleJson.VehicleState; - _sut = json.ToObject(); + _sut = json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + json); } diff --git a/test/Tesla.NET.Tests/Models/Internal/VehicleTests.cs b/test/Tesla.NET.Tests/Models/Internal/VehicleTests.cs index c408206..9a882bf 100644 --- a/test/Tesla.NET.Tests/Models/Internal/VehicleTests.cs +++ b/test/Tesla.NET.Tests/Models/Internal/VehicleTests.cs @@ -30,50 +30,52 @@ public When_serializing_Vehicle_Should_serialize(ITestOutputHelper output) public void fourteen_properties() => _json.Count.Should().Be(14); [Fact] - public void id() => _json["id"].Value().Should().Be(_sut.Id); + public void id() => Get("id").Value().Should().Be(_sut.Id); [Fact] - public void vehicle_id() => _json["vehicle_id"].Value().Should().Be(_sut.VehicleId); + public void vehicle_id() => Get("vehicle_id").Value().Should().Be(_sut.VehicleId); [Fact] - public void vin() => _json["vin"].Value().Should().Be(_sut.Vin); + public void vin() => Get("vin").Value().Should().Be(_sut.Vin); [Fact] - public void display_name() => _json["display_name"].Value().Should().Be(_sut.DisplayName); + public void display_name() => Get("display_name").Value().Should().Be(_sut.DisplayName); [Fact] - public void option_codes() => _json["option_codes"].Value().Should().Be(_sut.OptionCodes); + public void option_codes() => Get("option_codes").Value().Should().Be(_sut.OptionCodes); [Fact] - public void color() => _json["color"].Value().Should().Be(_sut.Color); + public void color() => Get("color").Value().Should().Be(_sut.Color); [Fact] public void tokens() => - _json["tokens"].Select(t => t.Value()).Should().BeEquivalentTo(_sut.Tokens, WithStrictOrdering); + Get("tokens").Select(t => t.Value()).Should().BeEquivalentTo(_sut.Tokens, WithStrictOrdering); [Fact] - public void state() => _json["state"].Value().Should().Be(_sut.State); + public void state() => Get("state").Value().Should().Be(_sut.State); [Fact] - public void in_service() => _json["in_service"].Value().Should().Be(_sut.InService); + public void in_service() => Get("in_service").Value().Should().Be(_sut.InService); [Fact] public void remote_start_enabled() => - _json["remote_start_enabled"].Value().Should().Be(_sut.RemoteStartEnabled); + Get("remote_start_enabled").Value().Should().Be(_sut.RemoteStartEnabled); [Fact] - public void calendar_enabled() => _json["calendar_enabled"].Value().Should().Be(_sut.CalendarEnabled); + public void calendar_enabled() => Get("calendar_enabled").Value().Should().Be(_sut.CalendarEnabled); [Fact] public void notifications_enabled() => - _json["notifications_enabled"].Value().Should().Be(_sut.NotificationsEnabled); + Get("notifications_enabled").Value().Should().Be(_sut.NotificationsEnabled); [Fact] - public void backseat_token() => _json["backseat_token"].Value().Should().Be(_sut.BackseatToken); + public void backseat_token() => Get("backseat_token").Value().Should().Be(_sut.BackseatToken); [Fact] public void backseat_token_updated_at() => - _json["backseat_token_updated_at"].Value().Should().Be(_sut.BackseatTokenUpdatedAt); + Get("backseat_token_updated_at").Value().Should().Be(_sut.BackseatTokenUpdatedAt); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_serializing_and_deserializing_Vehicle : FixtureContext @@ -89,7 +91,7 @@ public When_serializing_and_deserializing_Vehicle(ITestOutputHelper output) output.WriteLine("Serialized JSON:" + Environment.NewLine + json); - _actual = json.ToObject(); + _actual = json.ToObject() ?? throw new InvalidOperationException(); } [Fact] @@ -105,56 +107,58 @@ public When_deserializing_Vehicle_Should_deserialize(ITestOutputHelper output) : base(output) { _json = SampleJson.Vehicle; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] - public void id() => _sut.Id.Should().Be(_json["id"].Value()); + public void id() => _sut.Id.Should().Be(Get("id").Value()); [Fact] - public void vehicle_id() => _sut.VehicleId.Should().Be(_json["vehicle_id"].Value()); + public void vehicle_id() => _sut.VehicleId.Should().Be(Get("vehicle_id").Value()); [Fact] - public void vin() => _sut.Vin.Should().Be(_json["vin"].Value()); + public void vin() => _sut.Vin.Should().Be(Get("vin").Value()); [Fact] - public void display_name() => _sut.DisplayName.Should().Be(_json["display_name"].Value()); + public void display_name() => _sut.DisplayName.Should().Be(Get("display_name").Value()); [Fact] - public void option_codes() => _sut.OptionCodes.Should().Be(_json["option_codes"].Value()); + public void option_codes() => _sut.OptionCodes.Should().Be(Get("option_codes").Value()); [Fact] - public void color() => _sut.Color.Should().Be(_json["color"].Value()); + public void color() => _sut.Color.Should().Be(Get("color").Value()); [Fact] public void tokens() => - _sut.Tokens.Should().BeEquivalentTo(_json["tokens"].Select(t => t.Value()), WithStrictOrdering); + _sut.Tokens.Should().BeEquivalentTo(Get("tokens").Select(t => t.Value()), WithStrictOrdering); [Fact] - public void state() => _sut.State.Should().Be(_json["state"].Value()); + public void state() => _sut.State.Should().Be(Get("state").Value()); [Fact] - public void in_service() => _sut.InService.Should().Be(_json["in_service"].Value()); + public void in_service() => _sut.InService.Should().Be(Get("in_service").Value()); [Fact] public void remote_start_enabled() => - _sut.RemoteStartEnabled.Should().Be(_json["remote_start_enabled"].Value()); + _sut.RemoteStartEnabled.Should().Be(Get("remote_start_enabled").Value()); [Fact] - public void calendar_enabled() => _sut.CalendarEnabled.Should().Be(_json["calendar_enabled"].Value()); + public void calendar_enabled() => _sut.CalendarEnabled.Should().Be(Get("calendar_enabled").Value()); [Fact] public void notifications_enabled() => - _sut.NotificationsEnabled.Should().Be(_json["notifications_enabled"].Value()); + _sut.NotificationsEnabled.Should().Be(Get("notifications_enabled").Value()); [Fact] - public void backseat_token() => _sut.BackseatToken.Should().Be(_json["backseat_token"].Value()); + public void backseat_token() => _sut.BackseatToken.Should().Be(Get("backseat_token").Value()); [Fact] public void backseat_token_updated_at() => - _sut.BackseatTokenUpdatedAt.Should().Be(_json["backseat_token_updated_at"].Value()); + _sut.BackseatTokenUpdatedAt.Should().Be(Get("backseat_token_updated_at").Value()); + + private JToken Get(string name) => _json[name] ?? throw new InvalidOperationException($"'{name}' is null."); } public class When_deserializing_Vehicle_with_minimal_data_Should_default @@ -165,16 +169,16 @@ public class When_deserializing_Vehicle_with_minimal_data_Should_default public When_deserializing_Vehicle_with_minimal_data_Should_default(ITestOutputHelper output) { _json = SampleJson.VehicleMinimal; - _sut = _json.ToObject(); + _sut = _json.ToObject() ?? throw new InvalidOperationException(); output.WriteLine("Serialized JSON:" + Environment.NewLine + _json); } [Fact] - public void id() => _sut.Id.Should().Be(default(long)); + public void id() => _sut.Id.Should().Be(default); [Fact] - public void vehicle_id() => _sut.VehicleId.Should().Be(default(long)); + public void vehicle_id() => _sut.VehicleId.Should().Be(default); [Fact] public void vin() => _sut.Vin.Should().NotBeNull().And.BeEmpty(); diff --git a/test/Tesla.NET.Tests/Models/SampleJson.cs b/test/Tesla.NET.Tests/Models/SampleJson.cs index c506286..a03ab2e 100644 --- a/test/Tesla.NET.Tests/Models/SampleJson.cs +++ b/test/Tesla.NET.Tests/Models/SampleJson.cs @@ -9,33 +9,15 @@ namespace Tesla.NET.Models using System.Linq; using Newtonsoft.Json.Linq; - internal class SampleJson + internal static class SampleJson { - public static TJson Load(string fileName) - where TJson : JToken - { - Stream stream = - typeof(SampleJson).Assembly.GetManifestResourceStream(typeof(SampleJson), $"{fileName}.json"); - - if (stream == null) - throw new InvalidOperationException( - $"Unable to load Sample JSON file '{fileName}'" + - " - did you mark the file as an 'embedded resource'?"); - - using (var sr = new StreamReader(stream)) - { - string json = sr.ReadToEnd(); - return (TJson)JToken.Parse(json); - } - } - public static JObject AccessTokenResponse => Load(nameof(AccessTokenResponse)); - public static JObject ChargeState => (JObject)GetChargeStateResponse["response"]; + public static JObject ChargeState => GetChargeStateResponse.Response(); - public static JObject ChargeStateMinimal => (JObject)GetChargeStateMinimalResponse["response"]; + public static JObject ChargeStateMinimal => GetChargeStateMinimalResponse.Response(); - public static JObject DriveState => (JObject)GetDriveStateResponse["response"]; + public static JObject DriveState => GetDriveStateResponse.Response(); public static JObject DriveStateMinimal => new JObject(); @@ -51,12 +33,42 @@ public static TJson Load(string fileName) public static JObject GetVehicleStateResponse2 => Load(nameof(GetVehicleStateResponse2)); - public static JObject Vehicle => (JObject)GetVehiclesResponse["response"][0]; + public static JObject Vehicle => GetVehiclesResponse.FirstVehicle(); public static JObject VehicleMinimal => new JObject(); - public static JObject VehicleState => (JObject)GetVehicleStateResponse["response"]; + public static JObject VehicleState => GetVehicleStateResponse.Response(); public static JObject VehicleStateMinimal => new JObject(); + + public static TJson Load(string fileName) + where TJson : JToken + { + Stream? stream = + typeof(SampleJson).Assembly.GetManifestResourceStream(typeof(SampleJson), $"{fileName}.json"); + + if (stream == null) + { + throw new InvalidOperationException( + $"Unable to load Sample JSON file '{fileName}' - did you mark the file as an 'embedded resource'?"); + } + + using var sr = new StreamReader(stream); + string json = sr.ReadToEnd(); + return (TJson)JToken.Parse(json); + } + + private static JObject Response(this JToken data) + { + JObject response = (JObject?)data["response"] ?? throw new InvalidOperationException("response is null."); + return response; + } + + private static JObject FirstVehicle(this JToken data) + { + JArray response = (JArray?)data["response"] ?? throw new InvalidOperationException("response is null."); + JObject vehicle = (JObject?)response[0] ?? throw new InvalidOperationException("vehicle is null."); + return vehicle; + } } } diff --git a/test/Tesla.NET.Tests/RefreshAccessTokenTests.cs b/test/Tesla.NET.Tests/RefreshAccessTokenTests.cs index f455fea..4cebeaf 100644 --- a/test/Tesla.NET.Tests/RefreshAccessTokenTests.cs +++ b/test/Tesla.NET.Tests/RefreshAccessTokenTests.cs @@ -84,7 +84,7 @@ await Sut.RefreshAccessTokenAsync(_clientId, _clientSecret, _refreshToken) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters.Should().HaveCount(4); @@ -98,7 +98,7 @@ await Sut.RefreshAccessTokenAsync(_clientId, _clientSecret, _refreshToken) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -115,7 +115,7 @@ await Sut.RefreshAccessTokenAsync(_clientId, _clientSecret, _refreshToken) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -132,7 +132,7 @@ await Sut.RefreshAccessTokenAsync(_clientId, _clientSecret, _refreshToken) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -149,7 +149,7 @@ await Sut.RefreshAccessTokenAsync(_clientId, _clientSecret, _refreshToken) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -193,7 +193,7 @@ protected RefreshAccessTokenFailureTestsBase(ITestOutputHelper output, bool useC } [Fact] - public async Task Should_return_the_error_status_code() + public async Task Should_return_the_error_status_code() { // Act IMessageResponse actual = diff --git a/test/Tesla.NET.Tests/RequestAccessTokenTests.cs b/test/Tesla.NET.Tests/RequestAccessTokenTests.cs index 6988a13..a6d37b0 100644 --- a/test/Tesla.NET.Tests/RequestAccessTokenTests.cs +++ b/test/Tesla.NET.Tests/RequestAccessTokenTests.cs @@ -85,7 +85,7 @@ await Sut.RequestAccessTokenAsync(_clientId, _clientSecret, _email, _password) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters.Should().HaveCount(5); @@ -99,7 +99,7 @@ await Sut.RequestAccessTokenAsync(_clientId, _clientSecret, _email, _password) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -116,7 +116,7 @@ await Sut.RequestAccessTokenAsync(_clientId, _clientSecret, _email, _password) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -133,7 +133,7 @@ await Sut.RequestAccessTokenAsync(_clientId, _clientSecret, _email, _password) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -150,7 +150,7 @@ await Sut.RequestAccessTokenAsync(_clientId, _clientSecret, _email, _password) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -167,7 +167,7 @@ await Sut.RequestAccessTokenAsync(_clientId, _clientSecret, _email, _password) .ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters diff --git a/test/Tesla.NET.Tests/RequiresArgNullEx.cs b/test/Tesla.NET.Tests/RequiresArgNullEx.cs index 424c7ac..9aeb49b 100644 --- a/test/Tesla.NET.Tests/RequiresArgNullEx.cs +++ b/test/Tesla.NET.Tests/RequiresArgNullEx.cs @@ -14,7 +14,8 @@ namespace Tesla.NET public class RequiresArgNullEx { - [Theory, RequiresArgNullExAutoMoq(typeof(TeslaClientBase))] + [Theory] + [RequiresArgNullExAutoMoq(typeof(TeslaClientBase))] [Substitute(typeof(TeslaClientBase), typeof(TeslaAuthClient))] [Substitute(typeof(MessageResponse<>), typeof(MessageResponse))] [Substitute(typeof(ResponseDataWrapper<>), typeof(ResponseDataWrapper))] diff --git a/test/Tesla.NET.Tests/RevokeAccessTokenTests.cs b/test/Tesla.NET.Tests/RevokeAccessTokenTests.cs index 6392202..6fb826f 100644 --- a/test/Tesla.NET.Tests/RevokeAccessTokenTests.cs +++ b/test/Tesla.NET.Tests/RevokeAccessTokenTests.cs @@ -60,8 +60,8 @@ public async Task Should_set_the_bearer_token_with_the_specified_access_token() await Sut.RevokeAccessTokenAsync(_accessToken).ConfigureAwait(false); // Assert - Handler.Request.Headers.Authorization.Scheme.Should().Be("Bearer"); - Handler.Request.Headers.Authorization.Parameter.Should().Be(_accessToken); + Handler.Request.Headers.Authorization?.Scheme.Should().Be("Bearer"); + Handler.Request.Headers.Authorization?.Parameter.Should().Be(_accessToken); } [Fact] @@ -82,7 +82,7 @@ public async Task Should_POST_1_parameters() await Sut.RevokeAccessTokenAsync(_accessToken).ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters.Should().HaveCount(1); @@ -95,7 +95,7 @@ public async Task Should_POST_the_token_parameter() await Sut.RevokeAccessTokenAsync(_accessToken).ConfigureAwait(false); // Assert - string requestContent = Handler.RequestContents[0]; + string? requestContent = Handler.RequestContents[0]; Dictionary formParameters = QueryHelpers.ParseQuery(requestContent); formParameters @@ -135,7 +135,7 @@ protected RevokeAccessTokenFailureTestsBase(ITestOutputHelper output, bool useCu } [Fact] - public async Task Should_return_the_error_status_code() + public async Task Should_return_the_error_status_code() { // Act IMessageResponse actual = await Sut.RevokeAccessTokenAsync(_accessToken).ConfigureAwait(false); diff --git a/test/Tesla.NET.Tests/Tesla.NET.Tests.csproj b/test/Tesla.NET.Tests/Tesla.NET.Tests.csproj index 4c96c64..562a915 100644 --- a/test/Tesla.NET.Tests/Tesla.NET.Tests.csproj +++ b/test/Tesla.NET.Tests/Tesla.NET.Tests.csproj @@ -1,11 +1,15 @@  - net472;netcoreapp3.1 - latest + net5.0 Tesla.NET + True + latest + ..\test-stylecop.ruleset false + enable false + $(NoWarn);SA0001 @@ -15,17 +19,21 @@ all - runtime; build; native; contentfiles; analyzers + runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all - runtime; build; native; contentfiles; analyzers + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -44,9 +52,13 @@ - + + + + + PreserveNewest - + diff --git a/test/Tesla.NET.Tests/TeslaAuthClientInitializationTests.cs b/test/Tesla.NET.Tests/TeslaAuthClientInitializationTests.cs index e84ae7a..ab42061 100644 --- a/test/Tesla.NET.Tests/TeslaAuthClientInitializationTests.cs +++ b/test/Tesla.NET.Tests/TeslaAuthClientInitializationTests.cs @@ -22,7 +22,8 @@ public void Be_of_Type_ITeslaAuthClient() sut.Should().BeAssignableTo(); } - [Theory, AutoMoqData] + [Theory] + [AutoMoqData] public void Use_the_specified_Base_Uri(Uri baseUri) { // Arrange/Act @@ -32,7 +33,8 @@ public void Use_the_specified_Base_Uri(Uri baseUri) sut.BaseUri.Should().BeSameAs(baseUri); } - [Theory, AutoMoqData] + [Theory] + [AutoMoqData] public void Use_the_specified_HTTP_Client_and_Base_Uri(Uri baseUri, HttpClient client) { // Arrange/Act @@ -43,7 +45,8 @@ public void Use_the_specified_HTTP_Client_and_Base_Uri(Uri baseUri, HttpClient c sut.Client.Should().BeSameAs(client); } - [Theory, AutoMoqData] + [Theory] + [AutoMoqData] public void Use_the_specified_HTTP_Client(HttpClient client) { // Arrange/Act @@ -53,33 +56,18 @@ public void Use_the_specified_HTTP_Client(HttpClient client) sut.Client.Should().BeSameAs(client); } - [Fact] - public void Dispose_The_HttpClient() - { - // Arrange - var sut = new TeslaAuthClient(); - - // Act - sut.Dispose(); - - // Assert - sut.Client.Should().BeNull(); - sut.BaseUri.Should().BeNull(); - } - [Fact] public void Dispose_Is_Idempotent() { // Arrange var sut = new TeslaAuthClient(); + Action action = () => sut.Dispose(); // Act - sut.Dispose(); - sut.Dispose(); + action(); // Assert - sut.Client.Should().BeNull(); - sut.BaseUri.Should().BeNull(); + action.Should().NotThrow(); } } } diff --git a/test/Tesla.NET.Tests/TeslaClientInitializationTests.cs b/test/Tesla.NET.Tests/TeslaClientInitializationTests.cs index 08de117..bfd56d7 100644 --- a/test/Tesla.NET.Tests/TeslaClientInitializationTests.cs +++ b/test/Tesla.NET.Tests/TeslaClientInitializationTests.cs @@ -22,7 +22,8 @@ public void Be_of_Type_ITeslaClient() sut.Should().BeAssignableTo(); } - [Theory, AutoMoqData] + [Theory] + [AutoMoqData] public void Use_the_specified_Base_Uri(Uri baseUri) { // Arrange/Act @@ -32,7 +33,8 @@ public void Use_the_specified_Base_Uri(Uri baseUri) sut.BaseUri.Should().BeSameAs(baseUri); } - [Theory, AutoMoqData] + [Theory] + [AutoMoqData] public void Use_the_specified_HTTP_Client_and_Base_Uri(Uri baseUri, HttpClient client) { // Arrange/Act @@ -43,7 +45,8 @@ public void Use_the_specified_HTTP_Client_and_Base_Uri(Uri baseUri, HttpClient c sut.Client.Should().BeSameAs(client); } - [Theory, AutoMoqData] + [Theory] + [AutoMoqData] public void Use_the_specified_HTTP_Client(HttpClient client) { // Arrange/Act @@ -53,33 +56,18 @@ public void Use_the_specified_HTTP_Client(HttpClient client) sut.Client.Should().BeSameAs(client); } - [Fact] - public void Dispose_The_HttpClient() - { - // Arrange - var sut = new TeslaClient(); - - // Act - sut.Dispose(); - - // Assert - sut.Client.Should().BeNull(); - sut.BaseUri.Should().BeNull(); - } - [Fact] public void Dispose_Is_Idempotent() { // Arrange var sut = new TeslaClient(); + Action action = () => sut.Dispose(); // Act - sut.Dispose(); - sut.Dispose(); + action(); // Assert - sut.Client.Should().BeNull(); - sut.BaseUri.Should().BeNull(); + action.Should().NotThrow(); } } } diff --git a/test/Tesla.NET.Tests/TeslaClientMessageHandlerPipelineTests.cs b/test/Tesla.NET.Tests/TeslaClientMessageHandlerPipelineTests.cs index ee3430f..8a367ec 100644 --- a/test/Tesla.NET.Tests/TeslaClientMessageHandlerPipelineTests.cs +++ b/test/Tesla.NET.Tests/TeslaClientMessageHandlerPipelineTests.cs @@ -43,7 +43,7 @@ public void Should_create_a_chain_of_delegates() foreach (DelegatingHandler handler in _handlers) { current.Should().BeSameAs(handler); - current = handler.InnerHandler; + current = handler.InnerHandler!; } } @@ -55,10 +55,10 @@ public void Should_end_the_chain_with_a_HttpClientHandler() // Assert HttpMessageHandler current = result; - DelegatingHandler @delegate; + DelegatingHandler? @delegate; while ((@delegate = current as DelegatingHandler) != null) { - current = @delegate.InnerHandler; + current = @delegate.InnerHandler!; } current.Should().BeOfType(); @@ -99,7 +99,7 @@ public void Should_create_a_chain_of_delegates() foreach (DelegatingHandler handler in _handlers.OfType()) { current.Should().BeSameAs(handler); - current = handler.InnerHandler; + current = handler.InnerHandler!; } } @@ -111,10 +111,10 @@ public void Should_end_the_chain_with_the_last_HttpClientHandler() // Assert HttpMessageHandler current = result; - DelegatingHandler @delegate; + DelegatingHandler? @delegate; while ((@delegate = current as DelegatingHandler) != null) { - current = @delegate.InnerHandler; + current = @delegate.InnerHandler!; } current.Should().BeSameAs(_last); diff --git a/test/Tesla.NET.Tests/TeslaNetCustomization.cs b/test/Tesla.NET.Tests/TeslaNetCustomization.cs index a93f602..eb70a63 100644 --- a/test/Tesla.NET.Tests/TeslaNetCustomization.cs +++ b/test/Tesla.NET.Tests/TeslaNetCustomization.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2017 James Skimming. All rights reserved. +// Copyright (c) 2018 James Skimming. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. namespace Tesla.NET @@ -33,7 +33,8 @@ void ICustomization.Customize(IFixture fixture) [AttributeUsage(AttributeTargets.Method)] internal class AutoMoqDataAttribute : AutoDataAttribute { - public AutoMoqDataAttribute() : base(() => new Fixture().Customize(new TeslaNetCustomization())) + public AutoMoqDataAttribute() + : base(() => new Fixture().Customize(new TeslaNetCustomization())) { } } diff --git a/test/Tesla.NET.Tests/TestContexts.cs b/test/Tesla.NET.Tests/TestContexts.cs index 50334c2..487c930 100644 --- a/test/Tesla.NET.Tests/TestContexts.cs +++ b/test/Tesla.NET.Tests/TestContexts.cs @@ -24,11 +24,22 @@ protected FixtureContext(ITestOutputHelper output) Dispose(false); } - protected IFixture Fixture { get; private set; } = new Fixture().Customize(new TeslaNetCustomization()); + public StringBuilderTraceWriter TraceWriter { get; } = new StringBuilderTraceWriter(); - public StringBuilderTraceWriter TraceWriter { get; private set; } = new StringBuilderTraceWriter(); + public ITestOutputHelper Output { get; } - public ITestOutputHelper Output { get; private set; } + protected IFixture Fixture { get; } = new Fixture().Customize(new TeslaNetCustomization()); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public EquivalencyAssertionOptions WithStrictOrdering(EquivalencyAssertionOptions config) + { + return config.WithStrictOrdering().WithTracing(TraceWriter); + } protected virtual void Dispose(bool disposing) { @@ -42,21 +53,6 @@ protected virtual void Dispose(bool disposing) Output.WriteLine(faTrace); } } - - Fixture = null; - TraceWriter = null; - Output = null; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public EquivalencyAssertionOptions WithStrictOrdering(EquivalencyAssertionOptions config) - { - return config.WithStrictOrdering().WithTracing(TraceWriter); } } @@ -65,7 +61,7 @@ public class AuthRequestContext : FixtureContext protected AuthRequestContext(ITestOutputHelper output, bool useCustomBaseUri) : base(output) { - Uri baseUri = useCustomBaseUri ? Fixture.Create() : null; + Uri? baseUri = useCustomBaseUri ? Fixture.Create() : null; Handler = new TestHttpHandler(output); Sut = baseUri == null @@ -75,11 +71,11 @@ protected AuthRequestContext(ITestOutputHelper output, bool useCustomBaseUri) BaseUri = baseUri ?? TeslaClientBase.DefaultBaseUri; } - protected TestHttpHandler Handler { get; private set; } + protected TestHttpHandler Handler { get; } - protected TeslaAuthClient Sut { get; private set; } + protected TeslaAuthClient Sut { get; } - protected Uri BaseUri { get; private set; } + protected Uri BaseUri { get; } protected override void Dispose(bool disposing) { @@ -89,10 +85,6 @@ protected override void Dispose(bool disposing) Sut?.Dispose(); } - Handler = null; - Sut = null; - BaseUri = null; - base.Dispose(disposing); } } @@ -102,7 +94,7 @@ public class ClientRequestContext : FixtureContext protected ClientRequestContext(ITestOutputHelper output, bool useCustomBaseUri) : base(output) { - Uri baseUri = useCustomBaseUri ? Fixture.Create() : null; + Uri? baseUri = useCustomBaseUri ? Fixture.Create() : null; Handler = new TestHttpHandler(output); Sut = baseUri == null @@ -114,13 +106,13 @@ protected ClientRequestContext(ITestOutputHelper output, bool useCustomBaseUri) VehicleId = Fixture.Create(); } - protected TestHttpHandler Handler { get; private set; } + protected TestHttpHandler Handler { get; } - protected TeslaClient Sut { get; private set; } + protected TeslaClient Sut { get; } - protected Uri BaseUri { get; private set; } + protected Uri BaseUri { get; } - protected string AccessToken { get; private set; } + protected string AccessToken { get; } protected long VehicleId { get; } @@ -132,11 +124,6 @@ protected override void Dispose(bool disposing) Sut?.Dispose(); } - Handler = null; - Sut = null; - BaseUri = null; - AccessToken = null; - base.Dispose(disposing); } } diff --git a/test/Tesla.NET.Tests/xunit.runner.json b/test/Tesla.NET.Tests/xunit.runner.json index 805f25d..c720c97 100644 --- a/test/Tesla.NET.Tests/xunit.runner.json +++ b/test/Tesla.NET.Tests/xunit.runner.json @@ -1,4 +1,5 @@ { - "$schema": "https://xunit.github.io/schema/current/xunit.runner.schema.json", - "methodDisplayOptions": "replaceUnderscoreWithSpace, useOperatorMonikers, useEscapeSequences" + "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", + "methodDisplay": "method", + "methodDisplayOptions": "all" } diff --git a/test/stylecop.json b/test/stylecop.json new file mode 100644 index 0000000..46fe650 --- /dev/null +++ b/test/stylecop.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "copyrightText": "Copyright (c) 2018 James Skimming. All rights reserved.\nLicensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.", + "xmlHeader": false + }, + "layoutRules": { + "newlineAtEndOfFile": "require" + } + } +} diff --git a/test/test-stylecop.ruleset b/test/test-stylecop.ruleset new file mode 100644 index 0000000..be62c0f --- /dev/null +++ b/test/test-stylecop.ruleset @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file