diff --git a/.gitignore b/.gitignore index 3e759b7..6e6ed19 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,107 @@ + +# Created by https://www.gitignore.io/api/rider,dotnetcore,visualstudio,visualstudiocode +# Edit at https://www.gitignore.io/?templates=rider,dotnetcore,visualstudio,visualstudiocode + +### DotnetCore ### +# .NET Core build folders +/bin +/obj + +# Common node modules locations +/node_modules +/wwwroot/node_modules + + +### Rider ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### VisualStudioCode ### +.vscode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### VisualStudio ### ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files +*.rsuser *.suo *.user *.userosscache @@ -12,6 +110,9 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +# Mono auto generated files +mono_crash.* + # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -19,6 +120,8 @@ [Rr]eleases/ x64/ x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ @@ -36,9 +139,10 @@ Generated\ Files/ [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -# NUNIT +# NUnit *.VisualState.xml TestResult.xml +nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ @@ -52,7 +156,6 @@ BenchmarkDotNet.Artifacts/ project.lock.json project.fragment.lock.json artifacts/ -**/Properties/launchSettings.json # StyleCop StyleCopReport.xml @@ -60,9 +163,8 @@ StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c -*_i.h +*_h.h *.ilk -*.meta *.obj *.iobj *.pch @@ -77,6 +179,7 @@ StyleCopReport.xml *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log *.vspscc *.vssscc @@ -179,6 +282,8 @@ PublishScripts/ # NuGet Packages *.nupkg +# NuGet Symbol Packages +*.snupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. @@ -203,12 +308,14 @@ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx +*.appxbundle +*.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache -!*.[Cc]ache/ +!?*.[Cc]ache/ # Others ClientBin/ @@ -221,7 +328,7 @@ ClientBin/ *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk +# Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk @@ -252,6 +359,9 @@ ServiceFabricBackup/ *.bim.layout *.bim_*.settings *.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ @@ -287,12 +397,8 @@ paket-files/ # FAKE - F# Make .fake/ -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ +# CodeRush personal settings +.cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ @@ -317,7 +423,7 @@ __pycache__/ # OpenCover UI analysis results OpenCover/ -# Azure Stream Analytics local run output +# Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log @@ -326,5 +432,16 @@ ASALocalRun/ # NVidia Nsight GPU debugger configuration file *.nvuser -# MFractors (Xamarin productivity tool) working folder +# MFractors (Xamarin productivity tool) working folder .mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# End of https://www.gitignore.io/api/rider,dotnetcore,visualstudio,visualstudiocode diff --git a/README.md b/README.md index beff61d..5c923bf 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,25 @@ Install-Package ViaCEP The package has two classes: -- [ViaCEPClient](https://github.com/guibranco/ViaCEP/blob/master/ViaCEP/ViaCEPClient.cs) - The main class (methods) -- [ViaCEPResult](https://github.com/guibranco/ViaCEP/blob/master/ViaCEP/VIaCEPResult.cs) - The result class (data) +- [ViaCepClient](https://github.com/guibranco/ViaCEP/blob/master/ViaCEP/ViaCepClient.cs) - The main class (methods) +- [ViaCepResult](https://github.com/guibranco/ViaCEP/blob/master/ViaCEP/ViaCepResult.cs) - The result class (data) + +This package is fully compatible with Dependency Injection. Use the interface *IViaCepClient* and the constructor with HttpClient parameter with a IHttpClientFactory instance. + +``` +//your DI container +services.AddHttpClient(client =>{ + client.BaseAddress = new Uri("https://viacep.com.br/"); +}) + +``` You can search using the zip code/postal code (AKA CEP) or using the address data (state initials - UF, city name and location name - street, avenue, park, square). Both methods support async and sync! ## Querying by zip code / postal code (single result) ```cs -var result = ViaCEPClient.Search("01234567"); //searches for the postal code 01234-567 +var result = new ViaCepClient().Search("01234567"); //searches for the postal code 01234-567 var address = result.Address; var neighborhood = result.Neighborhood //do what you need with 'result' instance of ViaCEPResult. @@ -61,7 +71,7 @@ var neighborhood = result.Neighborhood ## Querying by address (list result) ```cs -var results = ViaCEPClient.Search("SP", "São Paulo", "Avenida Paulista"); //search for the Avenida Paulista in São Paulo / SP +var results = new ViaCepClient().Search("SP", "São Paulo", "Avenida Paulista"); //search for the Avenida Paulista in São Paulo / SP foreach(var result in results){ var address = result.Address; var neighborhood = result.Neighborhood; diff --git a/Src/ViaCEP/IViaCepClient.cs b/Src/ViaCEP/IViaCepClient.cs new file mode 100644 index 0000000..c4b574f --- /dev/null +++ b/Src/ViaCEP/IViaCepClient.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace ViaCep +{ + /// + /// The ViaCEP client interface. + /// + public interface IViaCepClient + { + + /// + /// Searches the specified zip code. + /// + /// The zip code. + /// + ViaCepResult Search(string zipCode); + + /// + /// Searches the asynchronous. + /// + /// The zip code. + /// The cancellation token. + /// + Task SearchAsync(string zipCode, CancellationToken cancellationToken); + + /// + /// Searches the specified state initials. + /// + /// The state initials. + /// The city. + /// The address. + /// + IEnumerable Search(string stateInitials, string city, string address); + + /// + /// Searches the asynchronous. + /// + /// The state initials. + /// The city. + /// The address. + /// The cancellation token. + /// + Task> SearchAsync(string stateInitials, string city, string address, CancellationToken cancellationToken); + + } +} diff --git a/Src/ViaCEP/VIaCEPResult.cs b/Src/ViaCEP/VIaCEPResult.cs index 63b8c9a..3c20f56 100644 --- a/Src/ViaCEP/VIaCEPResult.cs +++ b/Src/ViaCEP/VIaCEPResult.cs @@ -1,11 +1,11 @@ -namespace ViaCEP +namespace ViaCep { using Newtonsoft.Json; /// /// The Via CEP result class. /// - public sealed class ViaCEPResult + public sealed class ViaCepResult { /// /// Gets or sets the zip code. diff --git a/Src/ViaCEP/ViaCEP.csproj b/Src/ViaCEP/ViaCEP.csproj index f989f36..0b270f7 100644 --- a/Src/ViaCEP/ViaCEP.csproj +++ b/Src/ViaCEP/ViaCEP.csproj @@ -1,24 +1,30 @@ - - - A251D320-410E-48F1-889D-9F59EB8CFEB9 - netstandard2.0 - true - Guilherme Branco Stracini - The ViaCEP WebService client for .NET projects (both .NET Core and .NET Framework) - © 2020 Guilherme Branco Stracini. All rights reserved. - https://github.com/guibranco/ViaCEP/blob/master/LICENSE - https://github.com/guibranco/ViaCEP/ - https://github.com/guibranco/ViaCEP - GIT - - cep zipcode postalcode postal zip address location api webservice brasil brazil correios ibge gia mf fazenda - https://raw.githubusercontent.com/guibranco/ViaCEP/master/logo.png?v=1 - 1.0.0 - 1.0.0.0 - https://github.com/guibranco/ViaCEP/blob/master/LICENSE - - - - - - + + + + A251D320-410E-48F1-889D-9F59EB8CFEB9 + netstandard2.1 + true + Guilherme Branco Stracini + © 2020 Guilherme Branco Stracini. All rights reserved. + The ViaCEP WebService client for .NET projects (both .NET Core and .NET Framework) + https://github.com/guibranco/ViaCEP/ + https://github.com/guibranco/ViaCEP + GIT + cep zipcode postalcode postal zip address location api webservice brasil brazil correios ibge gia mf fazenda + https://raw.githubusercontent.com/guibranco/ViaCEP/master/logo.png?v=1 + logo.png + 1.0.0 + 1.0.0.0 + LICENSE + + + + + + + + + + + + diff --git a/Src/ViaCEP/ViaCEPClient.cs b/Src/ViaCEP/ViaCEPClient.cs index 5eaef69..acdd696 100644 --- a/Src/ViaCEP/ViaCEPClient.cs +++ b/Src/ViaCEP/ViaCEPClient.cs @@ -1,89 +1,108 @@ -namespace ViaCEP -{ - using System; - using System.Collections.Generic; - using System.Net.Http; - using System.Threading; - using System.Threading.Tasks; - - /// - /// The Via CEP client class. - /// - public static class ViaCEPClient - { - #region Private fields - - /// - /// The base URL - /// - private const string BaseUrl = "https://viacep.com.br"; - - #endregion - - #region Public methods - - /// - /// Searches the specified zip code. - /// - /// The zip code. - /// - public static ViaCEPResult Search(string zipCode) - { - return SearchAsync(zipCode, CancellationToken.None).Result; - } - - /// - /// Searches the asynchronous. - /// - /// The zip code. - /// The token. - /// - public static async Task SearchAsync(string zipCode, CancellationToken token) - { - using (var client = new HttpClient()) - { - client.BaseAddress = new Uri(BaseUrl); - var response = await client.GetAsync($"/ws/{zipCode}/json", token).ConfigureAwait(false); - response.EnsureSuccessStatusCode(); - return await response.Content.ReadAsAsync(token).ConfigureAwait(false); - } - } - - /// - /// Searches the specified state initials. - /// - /// The state initials. - /// The city. - /// The address. - /// - public static IEnumerable Search(string stateInitials, string city, string address) - { - return SearchAsync(stateInitials, city, address, CancellationToken.None).Result; - } - - /// - /// Searches the asynchronous. - /// - /// The state initials. - /// The city. - /// The address. - /// The token. - /// - public static async Task> SearchAsync( - string stateInitials, - string city, - string address, - CancellationToken token) - { - using (var client = new HttpClient()) - { - client.BaseAddress = new Uri(BaseUrl); - var response = await client.GetAsync($"/ws/{stateInitials}/{city}/{address}/json", token).ConfigureAwait(false); - response.EnsureSuccessStatusCode(); - return await response.Content.ReadAsAsync>(token).ConfigureAwait(false); - } - } - - #endregion - } -} +namespace ViaCep +{ + using System; + using System.Collections.Generic; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + /// + /// The Via CEP client class. + /// + public class ViaCepClient : IViaCepClient + { + #region Private fields + + /// + /// The base URL + /// + private const string BaseUrl = "https://viacep.com.br"; + + /// + /// The HTTP client + /// + private readonly HttpClient _httpClient; + + #endregion + + #region ~Ctors + + /// + /// Initializes a new instance of the class. + /// + public ViaCepClient() + { + _httpClient = HttpClientFactory.Create(); + _httpClient.BaseAddress = new Uri(BaseUrl); + } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP client. + public ViaCepClient(HttpClient httpClient) + { + _httpClient = httpClient; + } + + #endregion + + #region Public methods + + /// + /// Searches the specified zip code. + /// + /// The zip code. + /// + public ViaCepResult Search(string zipCode) + { + return SearchAsync(zipCode, CancellationToken.None).Result; + } + + /// + /// Searches the asynchronous. + /// + /// The zip code. + /// The token. + /// + public async Task SearchAsync(string zipCode, CancellationToken token) + { + var response = await _httpClient.GetAsync($"/ws/{zipCode}/json", token).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + return await response.Content.ReadAsAsync(token).ConfigureAwait(false); + } + + /// + /// Searches the specified state initials. + /// + /// The state initials. + /// The city. + /// The address. + /// + public IEnumerable Search(string stateInitials, string city, string address) + { + return SearchAsync(stateInitials, city, address, CancellationToken.None).Result; + } + + /// + /// Searches the asynchronous. + /// + /// The state initials. + /// The city. + /// The address. + /// The token. + /// + public async Task> SearchAsync( + string stateInitials, + string city, + string address, + CancellationToken token) + { + var response = await _httpClient.GetAsync($"/ws/{stateInitials}/{city}/{address}/json", token).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + return await response.Content.ReadAsAsync>(token).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/Tests/ViaCEP.Tests/AddressTests.cs b/Tests/ViaCEP.Tests/AddressTests.cs index 88175e8..7b4f3b4 100644 --- a/Tests/ViaCEP.Tests/AddressTests.cs +++ b/Tests/ViaCEP.Tests/AddressTests.cs @@ -1,29 +1,57 @@ -namespace ViaCEP.Tests -{ - using System; - using System.Linq; - using Xunit; - - /// - /// The address tests class. - /// - public class AddressTests - { - /// - /// Validates the search by full address. - /// - [Fact] - public void ValidateSearchByFullAddress() - { - var result = ViaCEPClient.Search("SP", "São Paulo", "Avenida Paulista"); - Assert.NotNull(result); - var list = result.ToList(); - Assert.True(list.Any()); - Assert.Contains(list, r => r.ZipCode.Equals("01310-905", StringComparison.InvariantCultureIgnoreCase)); - Assert.Contains(list, r => r.ZipCode.Equals("01311-941", StringComparison.InvariantCultureIgnoreCase)); - var first = list.First(); - Assert.Equal("SP", first.StateInitials); - Assert.Equal("São Paulo", first.City); - } - } +namespace ViaCep.Tests +{ + using System; + using System.Linq; + using Xunit; + using Moq; + using System.Threading; + using System.Threading.Tasks; + + /// + /// The address tests class. + /// + public class AddressTests + { + /// + /// Validates the search by full address. + /// + [Fact] + public void ValidateSearchByFullAddress() + { + var fixtureResults = ResultsFixture.GetSampleResults(); + var clientMock = new Mock(); + clientMock + .Setup(c => c.Search(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(fixtureResults); + + var results = clientMock.Object.Search(fixtureResults.First().StateInitials, fixtureResults.First().City, fixtureResults.First().Street); + Assert.NotNull(results); + + var list = results.ToList(); + Assert.True(list.Any()); + Assert.Contains(list, r => r.ZipCode.Equals("12345-678", StringComparison.InvariantCultureIgnoreCase)); + Assert.Contains(list, r => r.ZipCode.Equals("98765-432", StringComparison.InvariantCultureIgnoreCase)); + } + + /// + /// Validates the search by full address asynchronous. + /// + [Fact] + public async Task ValidateSearchByFullAddressAsync() + { + var fixtureResults = ResultsFixture.GetSampleResults(); + var clientMock = new Mock(); + clientMock + .Setup(c => c.SearchAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(fixtureResults); + + var results = await clientMock.Object.SearchAsync(fixtureResults.First().StateInitials, fixtureResults.First().City, fixtureResults.First().Street, CancellationToken.None); + Assert.NotNull(results); + + var list = results.ToList(); + Assert.True(list.Any()); + Assert.Contains(list, r => r.ZipCode.Equals("12345-678", StringComparison.InvariantCultureIgnoreCase)); + Assert.Contains(list, r => r.ZipCode.Equals("98765-432", StringComparison.InvariantCultureIgnoreCase)); + } + } } \ No newline at end of file diff --git a/Tests/ViaCEP.Tests/CoverageTests.cs b/Tests/ViaCEP.Tests/CoverageTests.cs new file mode 100644 index 0000000..68589d4 --- /dev/null +++ b/Tests/ViaCEP.Tests/CoverageTests.cs @@ -0,0 +1,86 @@ +using System; +using System.Linq; +using System.Net.Http; +using RichardSzalay.MockHttp; +using Xunit; + +namespace ViaCep.Tests +{ + /// + /// + /// + public class CoverageTests + { + /// + /// The base URL + /// + private readonly Uri _baseUrl = new Uri("https://viacep.com.br/"); + + /// + /// Validates the create new instance. + /// + [Fact] + public void ValidateCreateNewInstance() + { + var client = new ViaCepClient(); + Assert.NotNull(client); + } + + /// + /// Validates the search by zip code coverage. + /// + [Fact] + public void ValidateSearchByZipCodeCoverage() + { + const string resultData = "{'cep': '01001-000','logradouro': 'Praça da Sé','complemento': 'lado ímpar','bairro': 'Sé','localidade': 'São Paulo','uf': 'SP','unidade': '','ibge': '3550308','gia': '1004'}"; + var httpClientMock = new MockHttpMessageHandler(); + httpClientMock.When("https://viacep.com.br/ws/*/json") + .Respond("application/json", resultData); + + var httpClient = new HttpClient(httpClientMock) {BaseAddress = _baseUrl}; + var client = new ViaCepClient(httpClient); + + var result = client.Search("01001000"); + Assert.NotNull(result); + Assert.Equal("01001-000", result.ZipCode); + Assert.Equal("Praça da Sé", result.Street); + Assert.Equal("lado ímpar", result.Complement); + Assert.Equal("Sé", result.Neighborhood); + Assert.Equal("São Paulo", result.City); + Assert.Equal("SP", result.StateInitials); + Assert.Equal(string.Empty, result.Unit); + Assert.Equal(3550308, result.IBGECode); + Assert.True(result.GIACode.HasValue); + Assert.Equal(1004, result.GIACode); + } + + /// + /// Validates the search by address coverage. + /// + [Fact] + public void ValidateSearchByAddressCoverage() + { + const string resultData = + "[ { 'cep': '91790-072', 'logradouro': 'Rua Domingos José Poli', 'complemento': '', 'bairro': 'Restinga', 'localidade': 'Porto Alegre', 'uf': 'RS', 'unidade': '', 'ibge': '4314902', 'gia': '' }, { 'cep': '91910-420', 'logradouro': 'Rua José Domingos Varella', 'complemento': '', 'bairro': 'Cavalhada', 'localidade': 'Porto Alegre', 'uf': 'RS', 'unidade': '', 'ibge': '4314902', 'gia': '' }, { 'cep': '90420-200', 'logradouro': 'Rua Domingos José de Almeida', 'complemento': '', 'bairro': 'Rio Branco', 'localidade': 'Porto Alegre', 'uf': 'RS', 'unidade': '', 'ibge': '4314902', 'gia': '' } ]"; + var httpClientMock = new MockHttpMessageHandler(); + httpClientMock.When("https://viacep.com.br/ws/*/*/*/json") + .Respond("application/json", resultData); + + var httpClient = new HttpClient(httpClientMock) { BaseAddress = _baseUrl }; + var client = new ViaCepClient(httpClient); + + var results = client.Search("RS", "Porto Alegre", "Domingos Jose"); + Assert.NotNull(results); + + var list = results.ToList(); + Assert.Equal(3, list.Count); + Assert.All(list, result => Assert.False(result.GIACode.HasValue)); + Assert.All(list, result => Assert.Empty(result.Complement)); + Assert.All(list, result => Assert.Equal("Porto Alegre", result.City)); + Assert.All(list, result => Assert.Equal("RS", result.StateInitials)); + Assert.All(list, result => Assert.Equal(4314902, result.IBGECode)); + + } + + } +} diff --git a/Tests/ViaCEP.Tests/ResultsFixture.cs b/Tests/ViaCEP.Tests/ResultsFixture.cs new file mode 100644 index 0000000..eb3f0bd --- /dev/null +++ b/Tests/ViaCEP.Tests/ResultsFixture.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; + +namespace ViaCep.Tests +{ + internal static class ResultsFixture + { + public static ICollection GetSampleResults() => + new List + { + new ViaCepResult + { + Unit = "Any", + City = "São Paulo", + Complement = "", + GIACode = 1, + IBGECode = 1, + Neighborhood = "Centro", + StateInitials = "SP", + Street = "Rua Direita", + ZipCode = "12345-678" + }, + new ViaCepResult + { + Unit = "", + City = "São Paulo", + Complement = "", + GIACode = null, + IBGECode = 1, + Neighborhood = "Centro", + StateInitials = "SP", + Street = "Rua Direita", + ZipCode = "45632-870" + }, + new ViaCepResult + { + Unit = "", + City = "São Paulo", + Complement = "", + GIACode = 12, + IBGECode = 123, + Neighborhood = "Centro", + StateInitials = "SP", + Street = "Rua Direita", + ZipCode = "98765-432" + } + }; + } +} \ No newline at end of file diff --git a/Tests/ViaCEP.Tests/ViaCEP.Tests.csproj b/Tests/ViaCEP.Tests/ViaCEP.Tests.csproj index 98e3657..b01142f 100644 --- a/Tests/ViaCEP.Tests/ViaCEP.Tests.csproj +++ b/Tests/ViaCEP.Tests/ViaCEP.Tests.csproj @@ -1,8 +1,8 @@ - netcoreapp2.2 - + 2F57B9CD-5505-4456-B9FE-F91DCB4476D6 + netcoreapp3.1 false @@ -12,6 +12,8 @@ all + + all @@ -19,8 +21,8 @@ - - + + diff --git a/Tests/ViaCEP.Tests/ZipCodeTests.cs b/Tests/ViaCEP.Tests/ZipCodeTests.cs index 710700a..942104a 100644 --- a/Tests/ViaCEP.Tests/ZipCodeTests.cs +++ b/Tests/ViaCEP.Tests/ZipCodeTests.cs @@ -1,36 +1,114 @@ -namespace ViaCEP.Tests -{ - using Xunit; - - /// - /// The zip code tests class. - /// - public class ZipCodeTests - { - /// - /// Validates the search by zip code. - /// - [Fact] - public void ValidateSearchByZipCode() - { - var result = ViaCEPClient.Search("03177010"); - Assert.NotNull(result); - Assert.Equal("Rua Doutor João Batista de Lacerda", result.Street); - Assert.Equal("Quarta Parada", result.Neighborhood); - Assert.Equal("São Paulo", result.City); - Assert.Equal("SP", result.StateInitials); +using Moq; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ViaCep.Tests +{ + using Xunit; + + /// + /// The zip code tests class. + /// + public class ZipCodeTests + { + /// + /// Validates the search by zip code. + /// + [Fact] + public void ValidateSearchByZipCode() + { + var fixtureResults = ResultsFixture.GetSampleResults(); + var clientMock = new Mock(); + clientMock + .Setup(c => c.Search(It.IsAny())) + .Returns(fixtureResults.First(r => r.ZipCode.Equals("12345-678"))); + + var result = clientMock.Object.Search("12345678"); + Assert.NotNull(result); + Assert.Equal("Any", result.Unit); + Assert.Equal("Rua Direita", result.Street); + Assert.Equal(string.Empty, result.Complement); + Assert.Equal(1, result.GIACode); + Assert.Equal(1, result.IBGECode); + Assert.Equal("Centro", result.Neighborhood); + Assert.Equal("São Paulo", result.City); + Assert.Equal("SP", result.StateInitials); + } + + /// + /// Validates the search by zip code asynchronous. + /// + /// + [Fact] + public async Task ValidateSearchByZipCodeAsync() + { + var fixtureResults = ResultsFixture.GetSampleResults(); + var clientMock = new Mock(); + clientMock + .Setup(c => c.SearchAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(fixtureResults.First(r => r.ZipCode.Equals("12345-678"))); + + var result = await clientMock.Object.SearchAsync("12345678", CancellationToken.None); + Assert.NotNull(result); + Assert.Equal("Any", result.Unit); + Assert.Equal("Rua Direita", result.Street); + Assert.Equal(string.Empty, result.Complement); + Assert.Equal(1, result.GIACode); + Assert.Equal(1, result.IBGECode); + Assert.Equal("Centro", result.Neighborhood); + Assert.Equal("São Paulo", result.City); + Assert.Equal("SP", result.StateInitials); } - /// - /// Validates if the search by zip code don't throw a exception if the address doesn't have a gia code - /// - /// - [Fact] - public void ValidateSearchByZipCodeWithoutGiaCode() - { - var result = ViaCEPClient.Search("22795641"); - Assert.NotNull(result); - Assert.Null(result.GIACode); - } - } -} + + /// + /// Validates if the search by zip code don't throw a exception if the address doesn't have a gia code + /// + /// + [Fact] + public void ValidateSearchByZipCodeWithoutGiaCode() + { + var fixtureResults = ResultsFixture.GetSampleResults(); + var clientMock = new Mock(); + clientMock + .Setup(c => c.Search(It.IsAny())) + .Returns(fixtureResults.First(r => !r.GIACode.HasValue)); + + var result = clientMock.Object.Search("12345678"); + Assert.NotNull(result); + Assert.Equal("", result.Unit); + Assert.Equal("Rua Direita", result.Street); + Assert.Equal(string.Empty, result.Complement); + Assert.Null(result.GIACode); + Assert.Equal(1, result.IBGECode); + Assert.Equal("Centro", result.Neighborhood); + Assert.Equal("São Paulo", result.City); + Assert.Equal("SP", result.StateInitials); + } + + /// + /// Validates the search by zip code without gia code asynchronous. + /// + [Fact] + public async Task ValidateSearchByZipCodeWithoutGiaCodeAsync() + { + var fixtureResults = ResultsFixture.GetSampleResults(); + var clientMock = new Mock(); + clientMock + .Setup(c => c.SearchAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(fixtureResults.First(r => !r.GIACode.HasValue)); + + var result = await clientMock.Object.SearchAsync("12345678", CancellationToken.None); + Assert.NotNull(result); + Assert.Equal("", result.Unit); + Assert.Equal("Rua Direita", result.Street); + Assert.Equal(string.Empty, result.Complement); + Assert.Null(result.GIACode); + Assert.Equal(1, result.IBGECode); + Assert.Equal("Centro", result.Neighborhood); + Assert.Equal("São Paulo", result.City); + Assert.Equal("SP", result.StateInitials); + } + } +} \ No newline at end of file diff --git a/ViaCEP.sln b/ViaCEP.sln index 30c7f23..a750d93 100644 --- a/ViaCEP.sln +++ b/ViaCEP.sln @@ -7,9 +7,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Src", "Src", "{A8E8D875-205 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{474F8215-8B66-4E36-927C-E078635C7996}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViaCEP", "Src\ViaCEP\ViaCEP.csproj", "{A251D320-410E-48F1-889D-9F59EB8CFEB9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViaCep", "Src\ViaCep\ViaCep.csproj", "{A251D320-410E-48F1-889D-9F59EB8CFEB9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViaCEP.Tests", "Tests\ViaCEP.Tests\ViaCEP.Tests.csproj", "{D9FD0AA7-A4C5-43A2-820F-827BD503B52B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViaCep.Tests", "Tests\ViaCep.Tests\ViaCep.Tests.csproj", "{D9FD0AA7-A4C5-43A2-820F-827BD503B52B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5A1303EA-8DFA-48C6-A96D-EC71AE4EC0E8}" ProjectSection(SolutionItems) = preProject diff --git a/appveyor.yml b/appveyor.yml index 0f1105c..80580d1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,10 @@ -version: 2.0.{build} +version: 3.0.{build} skip_tags: true image: Visual Studio 2019 configuration: Release skip_commits: message: /(Create|Update).*\.(png|jpg|jpeg|bmp|gif|md)/ + environment: SOLUTION_NAME: ViaCEP SONAR_PROJECT: guibranco_ViaCEP @@ -12,6 +13,9 @@ environment: secure: b45J8d8RnM19gldF3sJX6UGacdYRXvyTYpubf1YUrGdHXZi+90NOtstyftjLXMSO GITHUB_TOKEN: secure: IEDiCuYBM8BnfdT90PGnvnKGEfHHHgzziGqfoZUUqTi1FgSkBXoMrAGbdLP6jNok + CODACY_PROJECT_TOKEN: + secure: AXFZSTVmZQGmLkM8Yw7bkdXLJ0bfQribvyeIYyhmU8rZgVsZ6qmFritTnzDBVIBb + dotnet_csproj: patch: true file: '**\*.csproj' @@ -20,16 +24,20 @@ dotnet_csproj: assembly_version: '{version}' file_version: '{version}' informational_version: '{version}' + before_build: - cmd: nuget restore - cmd: choco install opencover.portable - cmd: choco install codecov + build: publish_nuget: true include_nuget_references: true parallel: true verbosity: normal + build_script: + - curl -L https://github.com/codacy/codacy-coverage-reporter/releases/download/4.0.5/codacy-coverage-reporter-4.0.5-assembly.jar > ./codacy-test-reporter.jar - dotnet tool install --global dotnet-sonarscanner - ps: 'if (-Not $env:APPVEYOR_PULL_REQUEST_NUMBER) { & dotnet sonarscanner begin @@ -42,20 +50,30 @@ build_script: /d:sonar.coverage.exclusions="**/$env:SOLUTION_NAME.Tests/**,**/*Tests.cs" /d:sonar.cs.opencover.reportsPaths="$env:CD\Tests\$env:SOLUTION_NAME.Tests\coverage.opencover.xml" }' - dotnet build %SOLUTION_NAME%.sln - - ps: dotnet test .\Tests\$env:SOLUTION_NAME.Tests\$env:SOLUTION_NAME.Tests.csproj /p:CollectCoverage=true /p:CoverletOutputFormat="opencover" - - ps: 'if (-Not $env:APPVEYOR_PULL_REQUEST_NUMBER) { & dotnet sonarscanner end /d:sonar.login="$env:SONAR_TOKEN" }' + - dotnet test .\Tests\%SOLUTION_NAME%.Tests\%SOLUTION_NAME%.Tests.csproj /p:CollectCoverage=true /p:CoverletOutputFormat="opencover" + - dotnet test .\Tests\%SOLUTION_NAME%.Tests\%SOLUTION_NAME%.Tests.csproj /p:CollectCoverage=true /p:CoverletOutputFormat="cobertura" - codecov -f "%CD%\Tests\%SOLUTION_NAME%.Tests\coverage.opencover.xml" + - java -jar ./codacy-test-reporter.jar report -l CSharp -t %CODACY_PROJECT_TOKEN% -r %CD%\Tests\%SOLUTION_NAME%.Tests\coverage.cobertura.xml + - ps: 'if (-Not $env:APPVEYOR_PULL_REQUEST_NUMBER) { & dotnet sonarscanner end /d:sonar.login="$env:SONAR_TOKEN" }' + after_build: -- xcopy %CD%\Src\%SOLUTION_NAME%\bin\Release\netstandard2.0\*.* %CD%\Build\ +- xcopy %CD%\Src\%SOLUTION_NAME%\bin\Release\netstandard2.1\*.* %CD%\Build\ - copy %CD%\Src\%SOLUTION_NAME%\bin\Release\%SOLUTION_NAME%.%APPVEYOR_BUILD_VERSION%.nupkg %SOLUTION_NAME%.%APPVEYOR_BUILD_VERSION%.nupkg - rd /s /q %CD%\Src\%SOLUTION_NAME%\bin\Release\ +- xcopy %CD%\Tests\%SOLUTION_NAME%.Tests\*.xml %CD%\Coverage\ +- xcopy %CD%\Tests\%SOLUTION_NAME%.Tests\*.json %CD%\Coverage\ - cd %CD% - 7z a -tzip -mx9 "%SOLUTION_NAME%.%APPVEYOR_BUILD_VERSION%.zip" Build +- 7z a -tzip -mx9 "%SOLUTION_NAME%.%APPVEYOR_BUILD_VERSION%.Coverage.zip" Coverage + artifacts: - path: $(SOLUTION_NAME).%APPVEYOR_BUILD_VERSION%.zip name: ZipFile - path: $(SOLUTION_NAME).%APPVEYOR_BUILD_VERSION%.nupkg name: Package +- path: $(SOLUTION_NAME).%APPVEYOR_BUILD_VERSION%.Coverage.zip + name: Coverage + deploy: - provider: Environment name: NuGet