PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/EmpleoDotNet.Tests/Web/Controllers/JobOpportunityControllerTest.cs

https://gitlab.com/YhoanGaleano/empleo-dot-net
C# | 379 lines | 284 code | 62 blank | 33 comment | 7 complexity | 9342c73d3d4ecb4d465b10338a58bdd6 MD5 | raw file
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using System.Security.Principal;
  5. using System.Threading.Tasks;
  6. using System.Web;
  7. using System.Web.Mvc;
  8. using System.Web.Routing;
  9. using EmpleoDotNet.AppServices;
  10. using EmpleoDotNet.Controllers;
  11. using EmpleoDotNet.Core.Domain;
  12. using EmpleoDotNet.Core.Dto;
  13. using EmpleoDotNet.Helpers;
  14. using EmpleoDotNet.Helpers.Alerts;
  15. using EmpleoDotNet.Services.Social.Twitter;
  16. using EmpleoDotNet.ViewModel;
  17. using EmpleoDotNet.ViewModel.JobOpportunity;
  18. using FluentAssertions;
  19. using NSubstitute;
  20. using NSubstitute.ReturnsExtensions;
  21. using NUnit.Framework;
  22. using PagedList;
  23. using reCAPTCHA.MVC;
  24. // ReSharper disable Mvc.ActionNotResolved
  25. namespace EmpleoDotNet.Tests.Web.Controllers
  26. {
  27. [TestFixture]
  28. public class JobOpportunityControllerTest
  29. {
  30. private IJobOpportunityService _jobOpportunityService;
  31. private ITwitterService _twitterService;
  32. private JobOpportunityController _sut;
  33. [SetUp]
  34. public void SetUp()
  35. {
  36. _jobOpportunityService = Substitute.For<IJobOpportunityService>();
  37. _twitterService = Substitute.For<ITwitterService>();
  38. _sut = new JobOpportunityController(_jobOpportunityService, _twitterService, null);
  39. }
  40. #region Index
  41. [Test]
  42. public void Index_LocationNameNotNull_PlaceIdNull_ReturnsViewWithError()
  43. {
  44. // Arrange
  45. var param = new JobOpportunityPagingParameter {
  46. SelectedLocationPlaceId = null,
  47. SelectedLocationName = "Guachupita",
  48. JobCategory = JobCategory.All,
  49. Keyword = "myKeyword",
  50. IsRemote = true
  51. };
  52. var jobCategoriesCount = new[] { new JobCategoryCountDto() }.ToList();
  53. _jobOpportunityService.GetMainJobCategoriesCount().Returns(jobCategoriesCount);
  54. // Act
  55. var result = (AlertDecoratorResult)_sut.Index(param);
  56. // Assert
  57. _jobOpportunityService.Received(1).GetMainJobCategoriesCount();
  58. _jobOpportunityService.DidNotReceiveWithAnyArgs().GetAllJobOpportunitiesPagedByFilters(param);
  59. _sut.ModelState.IsValid.Should().BeFalse();
  60. _sut.ModelState.Should().ContainKey("SelectedLocationName");
  61. result.AlertClass.Should().Be("alert-danger");
  62. result.Message.Should().Be("Debe seleccionar una Localidad para buscar.");
  63. var viewResult = (ViewResult)result.InnerResult;
  64. var model = (JobOpportunitySearchViewModel)viewResult.Model;
  65. model.SelectedLocationLatitude.Should().Be(param.SelectedLocationLatitude);
  66. model.SelectedLocationLongitude.Should().Be(param.SelectedLocationLongitude);
  67. model.SelectedLocationPlaceId.Should().BeNull();
  68. model.SelectedLocationName.Should().Be(param.SelectedLocationName);
  69. model.JobCategory.Should().Be(param.JobCategory);
  70. model.Keyword.Should().Be(param.Keyword);
  71. model.IsRemote.Should().Be(param.IsRemote);
  72. model.CategoriesCount.Should().BeSameAs(jobCategoriesCount);
  73. model.Result.Should().BeEmpty();
  74. }
  75. [Test]
  76. public void Index_ReturnsRequestedDataCorrectly_LocationEmpty()
  77. {
  78. // Arrange
  79. var param = new JobOpportunityPagingParameter {
  80. SelectedLocationName = string.Empty,
  81. SelectedLocationLatitude = "18.686868",
  82. SelectedLocationLongitude = "-69.454545",
  83. SelectedLocationPlaceId = "111",
  84. JobCategory = JobCategory.All,
  85. Keyword = "myKeyword",
  86. IsRemote = true
  87. };
  88. var jobCategoriesCount = new[] { new JobCategoryCountDto() }.ToList();
  89. var jobOpportunityList = new[] { new JobOpportunity() }.ToPagedList(1, 1);
  90. _jobOpportunityService.GetMainJobCategoriesCount().Returns(jobCategoriesCount);
  91. _jobOpportunityService.GetAllJobOpportunitiesPagedByFilters(param).Returns(jobOpportunityList);
  92. // Act
  93. var result = (ViewResult)_sut.Index(param);
  94. // Assert
  95. _sut.ModelState.IsValid.Should().BeTrue();
  96. _jobOpportunityService.Received(1).GetMainJobCategoriesCount();
  97. _jobOpportunityService.Received(1).GetAllJobOpportunitiesPagedByFilters(param);
  98. var model = (JobOpportunitySearchViewModel)result.Model;
  99. model.SelectedLocationLatitude.Should().BeEmpty();
  100. model.SelectedLocationLongitude.Should().BeEmpty();
  101. model.SelectedLocationPlaceId.Should().BeEmpty();
  102. model.SelectedLocationName.Should().BeEmpty();
  103. model.JobCategory.Should().Be(param.JobCategory);
  104. model.Keyword.Should().Be(param.Keyword);
  105. model.IsRemote.Should().Be(param.IsRemote);
  106. model.CategoriesCount.Should().BeSameAs(jobCategoriesCount);
  107. model.Result.Should().BeSameAs(jobOpportunityList);
  108. }
  109. [Test]
  110. public void Index_ReturnsRequestedDataCorrectly_LocationNotEmpty()
  111. {
  112. // Arrange
  113. var param = new JobOpportunityPagingParameter {
  114. SelectedLocationName = "Santo Domingo",
  115. SelectedLocationLatitude = "18.686868",
  116. SelectedLocationLongitude = "-69.454545",
  117. SelectedLocationPlaceId = "111",
  118. JobCategory = JobCategory.All,
  119. Keyword = "myKeyword",
  120. IsRemote = true
  121. };
  122. var jobCategoriesCount = new[] { new JobCategoryCountDto() }.ToList();
  123. var jobOpportunityList = new[] { new JobOpportunity() }.ToPagedList(1, 1);
  124. _jobOpportunityService.GetMainJobCategoriesCount().Returns(jobCategoriesCount);
  125. _jobOpportunityService.GetAllJobOpportunitiesPagedByFilters(param).Returns(jobOpportunityList);
  126. // Act
  127. var result = (ViewResult)_sut.Index(param);
  128. // Assert
  129. _sut.ModelState.IsValid.Should().BeTrue();
  130. _jobOpportunityService.Received(1).GetMainJobCategoriesCount();
  131. _jobOpportunityService.Received(1).GetAllJobOpportunitiesPagedByFilters(param);
  132. var model = (JobOpportunitySearchViewModel)result.Model;
  133. model.SelectedLocationLatitude.Should().Be(param.SelectedLocationLatitude);
  134. model.SelectedLocationLongitude.Should().Be(param.SelectedLocationLongitude);
  135. model.SelectedLocationPlaceId.Should().Be(param.SelectedLocationPlaceId);
  136. model.SelectedLocationName.Should().Be(param.SelectedLocationName);
  137. model.JobCategory.Should().Be(param.JobCategory);
  138. model.Keyword.Should().Be(param.Keyword);
  139. model.IsRemote.Should().Be(param.IsRemote);
  140. model.CategoriesCount.Should().BeSameAs(jobCategoriesCount);
  141. model.Result.Should().BeSameAs(jobOpportunityList);
  142. }
  143. #endregion
  144. #region New
  145. [Test]
  146. public void New_GET_HasExpectedActionFilters()
  147. {
  148. // Arrange
  149. var controller = typeof(JobOpportunityController);
  150. var action = controller.GetMethod(nameof(JobOpportunityController.New),
  151. new Type[0]);
  152. // Act
  153. var filters = action.GetCustomAttributes().ToArray();
  154. // Assert
  155. filters.Should().ContainSingle(x => x is HttpGetAttribute);
  156. }
  157. [Test]
  158. public void New_GET_ReturnsView_WithEmptyModel()
  159. {
  160. // Arrange
  161. var model = new NewJobOpportunityViewModel();
  162. _sut.Url = Substitute.For<UrlHelper>();
  163. _sut.Url.Action("Wizard").Returns("/jobs/wizard");
  164. // Act
  165. var result = (AlertDecoratorResult)_sut.New();
  166. // Assert
  167. result.AlertClass.Should().Be("alert-info");
  168. result.Message.Should().Be(
  169. "Prueba nuestro nuevo proceso guiado de creación de posiciones haciendo "
  170. + "<b><a href='/jobs/wizard'>click aquí</a></b>");
  171. var viewResult = (ViewResult)result.InnerResult;
  172. viewResult.ViewName.Should().BeEmpty();
  173. ((NewJobOpportunityViewModel)viewResult.Model).ShouldBeEquivalentTo(model);
  174. }
  175. [Test]
  176. public void New_POST_HasExpectedActionFilters()
  177. {
  178. // Arrange
  179. var controller = typeof(JobOpportunityController);
  180. var action = controller.GetMethod(nameof(JobOpportunityController.New),
  181. new[] { typeof(NewJobOpportunityViewModel), typeof(bool) });
  182. // Act
  183. var filters = action.GetCustomAttributes().ToArray();
  184. // Assert
  185. filters.Should().ContainSingle(x => x is HttpPostAttribute);
  186. filters.Should().ContainSingle(x => x is ValidateAntiForgeryTokenAttribute);
  187. var validateInput = (ValidateInputAttribute)filters.Single(x => x is ValidateInputAttribute);
  188. var captchaValidator = (CaptchaValidatorAttribute)filters.Single(x => x is CaptchaValidatorAttribute);
  189. validateInput.EnableValidation.Should().BeFalse();
  190. captchaValidator.RequiredMessage.Should().Be("Por favor confirma que no eres un robot");
  191. }
  192. [Test]
  193. public async Task New_POST_ModelStateInvalid_ReturnsViewWithError()
  194. {
  195. // Arrange
  196. var model = new NewJobOpportunityViewModel();
  197. _sut.ModelState.AddModelError("", "");
  198. // Act
  199. var result = (AlertDecoratorResult)await _sut.New(model, false);
  200. // Assert
  201. _jobOpportunityService.DidNotReceiveWithAnyArgs().CreateNewJobOpportunity(null, string.Empty);
  202. await _twitterService.DidNotReceiveWithAnyArgs().PostNewJobOpportunity(null);
  203. _sut.ModelState.IsValid.Should().BeFalse();
  204. result.AlertClass.Should().Be("alert-danger");
  205. result.Message.Should().Be("Han ocurrido errores de validación que no permiten continuar el proceso");
  206. var innerResult = (ViewResult)result.InnerResult;
  207. innerResult.ViewName.Should().BeEmpty();
  208. innerResult.Model.Should().BeSameAs(model);
  209. }
  210. [Test]
  211. public async Task New_POST_LocationPlaceIdNullOrWhitespace_ReturnsViewWithError(
  212. [Values(null, "", " ")] string placeId
  213. )
  214. {
  215. // Arrange
  216. var model = new NewJobOpportunityViewModel { LocationPlaceId = placeId };
  217. // Act
  218. var result = (AlertDecoratorResult)await _sut.New(model, false);
  219. // Assert
  220. _jobOpportunityService.DidNotReceiveWithAnyArgs().CreateNewJobOpportunity(null,string.Empty);
  221. await _twitterService.DidNotReceiveWithAnyArgs().PostNewJobOpportunity(null);
  222. _sut.ModelState.IsValid.Should().BeFalse();
  223. _sut.ModelState.Should().ContainKey(nameof(model.LocationName));
  224. result.AlertClass.Should().Be("alert-danger");
  225. result.Message.Should().Be("Debe seleccionar una Localidad.");
  226. var innerResult = (ViewResult)result.InnerResult;
  227. innerResult.ViewName.Should().BeEmpty();
  228. innerResult.Model.Should().BeSameAs(model);
  229. }
  230. [Test]
  231. public async Task New_POST_ValidModel_CreatesJob_PostsTweet_RedirectsToDetail()
  232. {
  233. // Arrange
  234. var model = new NewJobOpportunityViewModel {
  235. Title = "myTitle",
  236. Category = JobCategory.MobileDevelopment,
  237. Description = "My description",
  238. CompanyName = "Company",
  239. CompanyUrl = "http://example.com",
  240. CompanyLogoUrl = "http://example.com/logo.png",
  241. CompanyEmail = "company@example.com",
  242. IsRemote = true,
  243. LocationName = "My location",
  244. LocationPlaceId = "123",
  245. LocationLatitude = "18.3939393",
  246. LocationLongitude = "-69.22222",
  247. JobType = JobType.FullTime
  248. };
  249. _sut.ControllerContext = GenerateControllerContext(_sut);
  250. _jobOpportunityService.WhenForAnyArgs(x => x.CreateNewJobOpportunity(null, null))
  251. .Do(x => { x.Arg<JobOpportunity>().Id = 1; });
  252. // Act
  253. var result = (RedirectToRouteResult)await _sut.New(model, false);
  254. // Assert
  255. _jobOpportunityService.Received(1).CreateNewJobOpportunity(
  256. Arg.Do<JobOpportunity>(entity => VerifyGeneratedJobOpportunityEntity(model, entity)), null);
  257. await _twitterService.Received(1).PostNewJobOpportunity(
  258. Arg.Do<JobOpportunity>(entity => VerifyGeneratedJobOpportunityEntity(model, entity)));
  259. result.RouteValues["action"].Should().Be(nameof(_sut.Detail));
  260. result.RouteValues["id"].Should().Be(UrlHelperExtensions.SeoUrl(1, "myTitle"));
  261. }
  262. private ControllerContext GenerateControllerContext(ControllerBase controller)
  263. {
  264. var fakeIdentity = new GenericIdentity("Jimmy");
  265. var fakeUser = new GenericPrincipal(fakeIdentity, null);
  266. var httpContext = new Moq.Mock<HttpContextBase>();
  267. httpContext.Setup(x => x.User).Returns(fakeUser);
  268. var reqContext = new RequestContext(httpContext.Object, new RouteData());
  269. return new ControllerContext(reqContext, controller);
  270. }
  271. private static void VerifyGeneratedJobOpportunityEntity(
  272. NewJobOpportunityViewModel model,
  273. JobOpportunity entity)
  274. {
  275. entity.Title.Should().Be(model.Title);
  276. entity.Category.Should().Be(model.Category);
  277. entity.Description.Should().Be(model.Description);
  278. entity.CompanyName.Should().Be(model.CompanyName);
  279. entity.CompanyUrl.Should().Be(model.CompanyUrl);
  280. entity.CompanyLogoUrl.Should().Be(model.CompanyLogoUrl);
  281. entity.CompanyEmail.Should().Be(model.CompanyEmail);
  282. entity.PublishedDate.Should().BeCloseTo(DateTime.Now);
  283. entity.IsRemote.Should().Be(model.IsRemote);
  284. entity.JobType.Should().Be(model.JobType);
  285. entity.JobOpportunityLocation.Should().Match<JobOpportunityLocation>(x =>
  286. x.Latitude == model.LocationLatitude
  287. && x.Longitude == model.LocationLongitude
  288. && x.Name == model.LocationName
  289. && x.PlaceId == model.LocationPlaceId
  290. );
  291. }
  292. #endregion
  293. #region Wizard
  294. [Test]
  295. public void Wizard_GET_HasExpectedActionFilters()
  296. {
  297. // Arrange
  298. var controller = typeof(JobOpportunityController);
  299. var action = controller.GetMethod(nameof(JobOpportunityController.Wizard),
  300. new Type[0]);
  301. // Act
  302. var filters = action.GetCustomAttributes().ToArray();
  303. // Assert
  304. filters.Should().ContainSingle(x => x is HttpGetAttribute);
  305. }
  306. [Test]
  307. public void Wizard_GET_ReturnsView()
  308. {
  309. // Act
  310. var result = (ViewResult)_sut.Wizard();
  311. // Assert
  312. result.ViewName.Should().BeEmpty();
  313. ((Wizard) result.Model).ShouldBeEquivalentTo(new Wizard());
  314. }
  315. #endregion
  316. }
  317. }