diff options
| author | Danail Dimitrov <danaildimitrov321@gmail.com> | 2021-03-14 21:40:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-14 21:40:12 +0200 |
| commit | ac82c773a5ec43c6a59d3d0b7665b67ac9e6bdde (patch) | |
| tree | 8d57d347dd56642105998c3cc3d12bd16ac49aa1 /src | |
| parent | 432fc5890814596d50fb409a6e5dc952d7bb4836 (diff) | |
| parent | 76f71bb8cab45922f3e4999253a1567a0e4af3db (diff) | |
| download | DevHive-ac82c773a5ec43c6a59d3d0b7665b67ac9e6bdde.tar DevHive-ac82c773a5ec43c6a59d3d0b7665b67ac9e6bdde.tar.gz DevHive-ac82c773a5ec43c6a59d3d0b7665b67ac9e6bdde.zip | |
Merge pull request #22 from Team-Kaleidoscope/rating_system
Rating system
Diffstat (limited to 'src')
18 files changed, 1684 insertions, 31 deletions
diff --git a/src/Data/DevHive.Data.Tests/RatingRepository.Tests.cs b/src/Data/DevHive.Data.Tests/RatingRepository.Tests.cs new file mode 100644 index 0000000..2da90d9 --- /dev/null +++ b/src/Data/DevHive.Data.Tests/RatingRepository.Tests.cs @@ -0,0 +1,188 @@ +using DevHive.Data.Repositories; +using Microsoft.EntityFrameworkCore; +using NUnit.Framework; +using System.Threading.Tasks; +using DevHive.Data.Models; +using System.Linq; +using System; +using System.Collections.Generic; + +namespace DevHive.Data.Tests +{ + [TestFixture] + public class RatingRepositoryTests + { + private DevHiveContext _context; + private RatingRepository _ratingRepository; + + #region Setups + [SetUp] + public void Setup() + { + var optionsBuilder = new DbContextOptionsBuilder<DevHiveContext>() + .UseInMemoryDatabase(databaseName: "DevHive_Test_Database"); + + this._context = new DevHiveContext(optionsBuilder.Options); + this._ratingRepository = new RatingRepository(this._context, null); + } + + [TearDown] + public void TearDown() + { + this._context.Database.EnsureDeleted(); + } + #endregion + + #region GetById + [Test] + public async Task GetByIdAsync_ReturnsTheCorrectRating_IfItExists() + { + Guid ratingId = Guid.NewGuid(); + await AddDummyRating(ratingId); + + Rating ratingResult = await this._ratingRepository.GetByIdAsync(ratingId); + + Assert.AreEqual(ratingResult.Id, ratingId); + } + + [Test] + public async Task GetByIdAsync_ReturnsNull_IfRatingDoesNotExist() + { + Rating ratingResult = await this._ratingRepository.GetByIdAsync(Guid.NewGuid()); + + Assert.IsNull(ratingResult); + } + #endregion + + #region GetByPostId + [Test] + public async Task GetRatingsByPostId_ReturnsFilledListOfRatings_WhenTheyExist() + { + Guid postId = Guid.NewGuid(); + await AddDummyPost(postId); + await AddDummyRating(Guid.NewGuid(), postId); + await AddDummyRating(Guid.NewGuid(), postId); + + List<Rating> result = await this._ratingRepository.GetRatingsByPostId(postId); + + Assert.IsNotEmpty(result); + } + + [Test] + public async Task GetRatingsByPostId_ReturnsEmptyList_WhenThereAreNoRatings() + { + List<Rating> result = await this._ratingRepository.GetRatingsByPostId(Guid.NewGuid()); + + Assert.IsEmpty(result); + } + #endregion + + #region GetByUserAndPostId + [Test] + public async Task GetRatingByUserAndPostId_ReturnsRating_WhenItExists() + { + Guid ratingId = Guid.NewGuid(); + Guid postId = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + await AddDummyPost(postId); + await AddDummyUser(userId); + await AddDummyRating(ratingId, postId, userId); + + Rating result = await this._ratingRepository.GetRatingByUserAndPostId(userId, postId); + + Assert.AreEqual(result.Id, ratingId); + } + + [Test] + public async Task GetRatingByUserAndPostId_ReturnsNull_WhenRatingDoesNotExist() + { + Rating result = await this._ratingRepository.GetRatingByUserAndPostId(Guid.NewGuid(), Guid.NewGuid()); + + Assert.IsNull(result); + } + #endregion + + #region UserRatedPost + [Test] + public async Task UserRatedPost_ReturnsTrue_WhenUserHasRatedPost() + { + Guid postId = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + await AddDummyPost(postId); + await AddDummyUser(userId); + await AddDummyRating(Guid.NewGuid(), postId, userId); + + bool result = await this._ratingRepository.UserRatedPost(userId, postId); + + Assert.IsTrue(result); + } + + [Test] + public async Task UserRatedPost_ReturnsFalse_WhenUserHasNotRatedPost() + { + bool result = await this._ratingRepository.UserRatedPost(Guid.NewGuid(), Guid.NewGuid()); + + Assert.IsFalse(result); + } + #endregion + + #region DoesRatingExist + [Test] + public async Task DoesRatingExist_ReturnsTrue_WhenItExists() + { + Guid ratingId = Guid.NewGuid(); + await AddDummyRating(ratingId); + + bool result = await this._ratingRepository.DoesRatingExist(ratingId); + + Assert.IsTrue(result); + } + + [Test] + public async Task DoesRatingExist_ReturnsFalse_WhenRatingDoesNotExist() + { + bool result = await this._ratingRepository.DoesRatingExist(Guid.NewGuid()); + + Assert.IsFalse(result); + } + #endregion + + #region HelperMethods + private async Task AddDummyRating(Guid ratingId, Guid postId = default(Guid), Guid userId = default(Guid)) + { + Rating rating = new Rating + { + Id = ratingId, + Post = this._context.Posts.FirstOrDefault(x => x.Id == postId), + User = this._context.Users.FirstOrDefault(x => x.Id == userId) + }; + + await this._context.Rating.AddAsync(rating); + await this._context.SaveChangesAsync(); + } + + private async Task AddDummyPost(Guid postId) + { + Post post = new Post() + { + Id = postId, + Message = "Never gonna give you up" + }; + + await this._context.Posts.AddAsync(post); + await this._context.SaveChangesAsync(); + } + + private async Task AddDummyUser(Guid userId) + { + User user = new User() + { + Id = userId + }; + + await this._context.Users.AddAsync(user); + await this._context.SaveChangesAsync(); + } + #endregion + } +} diff --git a/src/Data/DevHive.Data/Migrations/20210303083146_rating_migrations_update.Designer.cs b/src/Data/DevHive.Data/Migrations/20210303083146_rating_migrations_update.Designer.cs new file mode 100644 index 0000000..ff5dd1c --- /dev/null +++ b/src/Data/DevHive.Data/Migrations/20210303083146_rating_migrations_update.Designer.cs @@ -0,0 +1,675 @@ +// <auto-generated /> +using System; +using DevHive.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace DevHive.Data.Migrations +{ + [DbContext(typeof(DevHiveContext))] + [Migration("20210303083146_rating_migrations_update")] + partial class rating_migrations_update + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 63) + .HasAnnotation("ProductVersion", "5.0.3") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + modelBuilder.Entity("DevHive.Data.Models.Comment", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<Guid?>("CreatorId") + .HasColumnType("uuid"); + + b.Property<string>("Message") + .HasColumnType("text"); + + b.Property<Guid?>("PostId") + .HasColumnType("uuid"); + + b.Property<DateTime>("TimeCreated") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("PostId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Language", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<string>("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Languages"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Post", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<Guid?>("CreatorId") + .HasColumnType("uuid"); + + b.Property<string>("Message") + .HasColumnType("text"); + + b.Property<DateTime>("TimeCreated") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.ToTable("Posts"); + }); + + modelBuilder.Entity("DevHive.Data.Models.ProfilePicture", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<string>("PictureURL") + .HasColumnType("text"); + + b.Property<Guid>("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ProfilePicture"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Rating", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<bool>("IsLike") + .HasColumnType("boolean"); + + b.Property<Guid?>("PostId") + .HasColumnType("uuid"); + + b.Property<Guid?>("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("UserId"); + + b.ToTable("Rating"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Relational.PostAttachments", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<string>("FileUrl") + .HasColumnType("text"); + + b.Property<Guid?>("PostId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("PostAttachments"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Relational.RatedPost", b => + { + b.Property<Guid>("UserId") + .HasColumnType("uuid"); + + b.Property<Guid>("PostId") + .HasColumnType("uuid"); + + b.HasKey("UserId", "PostId"); + + b.HasIndex("PostId"); + + b.ToTable("RatedPosts"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Relational.UserRate", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<bool>("Liked") + .HasColumnType("boolean"); + + b.Property<Guid?>("PostId") + .HasColumnType("uuid"); + + b.Property<Guid?>("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRates"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Role", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property<string>("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property<string>("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Technology", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<string>("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Technologies"); + }); + + modelBuilder.Entity("DevHive.Data.Models.User", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property<int>("AccessFailedCount") + .HasColumnType("integer"); + + b.Property<string>("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property<string>("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property<bool>("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property<string>("FirstName") + .HasColumnType("text"); + + b.Property<string>("LastName") + .HasColumnType("text"); + + b.Property<bool>("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property<DateTimeOffset?>("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property<string>("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property<string>("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property<string>("PasswordHash") + .HasColumnType("text"); + + b.Property<string>("PhoneNumber") + .HasColumnType("text"); + + b.Property<bool>("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property<string>("SecurityStamp") + .HasColumnType("text"); + + b.Property<bool>("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property<Guid?>("UserId") + .HasColumnType("uuid"); + + b.Property<string>("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("UserId"); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("LanguageUser", b => + { + b.Property<Guid>("LanguagesId") + .HasColumnType("uuid"); + + b.Property<Guid>("UsersId") + .HasColumnType("uuid"); + + b.HasKey("LanguagesId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("LanguageUser"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("ClaimType") + .HasColumnType("text"); + + b.Property<string>("ClaimValue") + .HasColumnType("text"); + + b.Property<Guid>("RoleId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("ClaimType") + .HasColumnType("text"); + + b.Property<string>("ClaimValue") + .HasColumnType("text"); + + b.Property<Guid>("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => + { + b.Property<string>("LoginProvider") + .HasColumnType("text"); + + b.Property<string>("ProviderKey") + .HasColumnType("text"); + + b.Property<string>("ProviderDisplayName") + .HasColumnType("text"); + + b.Property<Guid>("UserId") + .HasColumnType("uuid"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b => + { + b.Property<Guid>("UserId") + .HasColumnType("uuid"); + + b.Property<Guid>("RoleId") + .HasColumnType("uuid"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => + { + b.Property<Guid>("UserId") + .HasColumnType("uuid"); + + b.Property<string>("LoginProvider") + .HasColumnType("text"); + + b.Property<string>("Name") + .HasColumnType("text"); + + b.Property<string>("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("RoleUser", b => + { + b.Property<Guid>("RolesId") + .HasColumnType("uuid"); + + b.Property<Guid>("UsersId") + .HasColumnType("uuid"); + + b.HasKey("RolesId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("RoleUser"); + }); + + modelBuilder.Entity("TechnologyUser", b => + { + b.Property<Guid>("TechnologiesId") + .HasColumnType("uuid"); + + b.Property<Guid>("UsersId") + .HasColumnType("uuid"); + + b.HasKey("TechnologiesId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("TechnologyUser"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Comment", b => + { + b.HasOne("DevHive.Data.Models.User", "Creator") + .WithMany("Comments") + .HasForeignKey("CreatorId"); + + b.HasOne("DevHive.Data.Models.Post", "Post") + .WithMany("Comments") + .HasForeignKey("PostId"); + + b.Navigation("Creator"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Post", b => + { + b.HasOne("DevHive.Data.Models.User", "Creator") + .WithMany("Posts") + .HasForeignKey("CreatorId"); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("DevHive.Data.Models.ProfilePicture", b => + { + b.HasOne("DevHive.Data.Models.User", "User") + .WithOne("ProfilePicture") + .HasForeignKey("DevHive.Data.Models.ProfilePicture", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Rating", b => + { + b.HasOne("DevHive.Data.Models.Post", "Post") + .WithMany("Ratings") + .HasForeignKey("PostId"); + + b.HasOne("DevHive.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Post"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Relational.PostAttachments", b => + { + b.HasOne("DevHive.Data.Models.Post", "Post") + .WithMany("Attachments") + .HasForeignKey("PostId"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Relational.RatedPost", b => + { + b.HasOne("DevHive.Data.Models.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevHive.Data.Models.User", "User") + .WithMany("RatedPosts") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("DevHive.Data.Models.Relational.UserRate", b => + { + b.HasOne("DevHive.Data.Models.Post", "Post") + .WithMany() + .HasForeignKey("PostId"); + + b.HasOne("DevHive.Data.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Post"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("DevHive.Data.Models.User", b => + { + b.HasOne("DevHive.Data.Models.User", null) + .WithMany("Friends") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("LanguageUser", b => + { + b.HasOne("DevHive.Data.Models.Language", null) + .WithMany() + .HasForeignKey("LanguagesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b => + { + b.HasOne("DevHive.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => + { + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => + { + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b => + { + b.HasOne("DevHive.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => + { + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleUser", b => + { + b.HasOne("DevHive.Data.Models.Role", null) + .WithMany() + .HasForeignKey("RolesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TechnologyUser", b => + { + b.HasOne("DevHive.Data.Models.Technology", null) + .WithMany() + .HasForeignKey("TechnologiesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevHive.Data.Models.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DevHive.Data.Models.Post", b => + { + b.Navigation("Attachments"); + + b.Navigation("Comments"); + + b.Navigation("Ratings"); + }); + + modelBuilder.Entity("DevHive.Data.Models.User", b => + { + b.Navigation("Comments"); + + b.Navigation("Friends"); + + b.Navigation("Posts"); + + b.Navigation("ProfilePicture"); + + b.Navigation("RatedPosts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Data/DevHive.Data/Migrations/20210303083146_rating_migrations_update.cs b/src/Data/DevHive.Data/Migrations/20210303083146_rating_migrations_update.cs new file mode 100644 index 0000000..073ba50 --- /dev/null +++ b/src/Data/DevHive.Data/Migrations/20210303083146_rating_migrations_update.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DevHive.Data.Migrations +{ + public partial class rating_migrations_update : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CurrentRating", + table: "Posts"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn<int>( + name: "CurrentRating", + table: "Posts", + type: "integer", + nullable: false, + defaultValue: 0); + } + } +} diff --git a/src/Data/DevHive.Data/Migrations/DevHiveContextModelSnapshot.cs b/src/Data/DevHive.Data/Migrations/DevHiveContextModelSnapshot.cs index a722cb2..80e3ac0 100644 --- a/src/Data/DevHive.Data/Migrations/DevHiveContextModelSnapshot.cs +++ b/src/Data/DevHive.Data/Migrations/DevHiveContextModelSnapshot.cs @@ -69,9 +69,6 @@ namespace DevHive.Data.Migrations b.Property<Guid?>("CreatorId") .HasColumnType("uuid"); - b.Property<int>("CurrentRating") - .HasColumnType("integer"); - b.Property<string>("Message") .HasColumnType("text"); diff --git a/src/Data/DevHive.Data/Repositories/RatingRepository.cs b/src/Data/DevHive.Data/Repositories/RatingRepository.cs index 9bb2368..c35f6d5 100644 --- a/src/Data/DevHive.Data/Repositories/RatingRepository.cs +++ b/src/Data/DevHive.Data/Repositories/RatingRepository.cs @@ -27,23 +27,49 @@ namespace DevHive.Data.Repositories .Include(x => x.Post) .FirstOrDefaultAsync(x => x.Id == id); } + /// <summary> + /// Gets all the ratings for a psot. + /// </summary> + /// <param name="postId">Id of the post.</param> + /// <returns></returns> public async Task<List<Rating>> GetRatingsByPostId(Guid postId) { return await this._context.Rating + .Include(x => x.User) + .Include(x => x.Post) .Where(x => x.Post.Id == postId).ToListAsync(); } + /// <summary> + /// Checks if a user rated a given post. In DevHive every user has one or no rating for every post. + /// </summary> + /// <param name="userId">Id of the user.</param> + /// <param name="postId">Id of the psot.</param> + /// <returns>True if the user has already rated the post and false if he hasn't.</returns> public async Task<bool> UserRatedPost(Guid userId, Guid postId) { return await this._context.Rating .Where(x => x.Post.Id == postId) .AnyAsync(x => x.User.Id == userId); } + /// <summary> + /// Gets a rating by the post to which the rating corresponds and the user who created it. + /// </summary> + /// <param name="userId">Id of the user.</param> + /// <param name="postId">Id of the post.</param> + /// <returns>Rating for the given post by the given user.</returns> public async Task<Rating> GetRatingByUserAndPostId(Guid userId, Guid postId) { return await this._context.Rating + .Include(x => x.User) + .Include(x => x.Post) .FirstOrDefaultAsync(x => x.Post.Id == postId && x.User.Id == userId); } + /// <summary> + /// Checks if a given rating already exist + /// </summary> + /// <param name="id">Id of the rating</param> + /// <returns>True if the rating exists and false if it does not.</returns> public async Task<bool> DoesRatingExist(Guid id) { return await this._context.Rating diff --git a/src/Services/DevHive.Services.Models/Post/Rating/CreateRatingServiceModel.cs b/src/Services/DevHive.Services.Models/Rating/CreateRatingServiceModel.cs index aaeab73..486e3d2 100644 --- a/src/Services/DevHive.Services.Models/Post/Rating/CreateRatingServiceModel.cs +++ b/src/Services/DevHive.Services.Models/Rating/CreateRatingServiceModel.cs @@ -1,6 +1,6 @@ using System; -namespace DevHive.Services.Models.Post.Rating +namespace DevHive.Services.Models.Rating { public class CreateRatingServiceModel { diff --git a/src/Services/DevHive.Services.Models/Post/Rating/ReadRatingServiceModel.cs b/src/Services/DevHive.Services.Models/Rating/ReadRatingServiceModel.cs index 86b4957..56a5ab0 100644 --- a/src/Services/DevHive.Services.Models/Post/Rating/ReadRatingServiceModel.cs +++ b/src/Services/DevHive.Services.Models/Rating/ReadRatingServiceModel.cs @@ -1,6 +1,6 @@ using System; -namespace DevHive.Services.Models.Post.Rating +namespace DevHive.Services.Models.Rating { public class ReadRatingServiceModel { diff --git a/src/Services/DevHive.Services.Models/Post/Rating/UpdateRatingServiceModel.cs b/src/Services/DevHive.Services.Models/Rating/UpdateRatingServiceModel.cs index 1ea8d8f..923e789 100644 --- a/src/Services/DevHive.Services.Models/Post/Rating/UpdateRatingServiceModel.cs +++ b/src/Services/DevHive.Services.Models/Rating/UpdateRatingServiceModel.cs @@ -1,6 +1,6 @@ using System; -namespace DevHive.Services.Models.Post.Rating +namespace DevHive.Services.Models.Rating { public class UpdateRatingServiceModel { diff --git a/src/Services/DevHive.Services.Tests/RatingService.Tests.cs b/src/Services/DevHive.Services.Tests/RatingService.Tests.cs new file mode 100644 index 0000000..5f84530 --- /dev/null +++ b/src/Services/DevHive.Services.Tests/RatingService.Tests.cs @@ -0,0 +1,448 @@ +using System; +using System.Threading.Tasks; +using AutoMapper; +using DevHive.Data.Interfaces; +using DevHive.Data.Models; +using DevHive.Services.Models.Rating; +using DevHive.Services.Services; +using Moq; +using NUnit.Framework; + +namespace DevHive.Services.Tests +{ + [TestFixture] + public class RatingServiceTests + { + private Mock<IPostRepository> _postRepositoryMock; + private Mock<IRatingRepository> _ratingRepositoryMock; + private Mock<IUserRepository> _userRepositoryMock; + private Mock<IMapper> _mapperMock; + private RatingService _ratingService; + + #region SetUps + [SetUp] + public void SetUp() + { + this._postRepositoryMock = new Mock<IPostRepository>(); + this._ratingRepositoryMock = new Mock<IRatingRepository>(); + this._userRepositoryMock = new Mock<IUserRepository>(); + this._mapperMock = new Mock<IMapper>(); + this._ratingService = new RatingService(this._postRepositoryMock.Object, this._ratingRepositoryMock.Object, this._userRepositoryMock.Object, this._mapperMock.Object); + } + #endregion + + #region Create + [Test] + public async Task RatePost_ReturnsNonEmptyGuid_WhenEntityIsAddedSuccessfully() + { + bool isLike = true; + Guid id = Guid.NewGuid(); + Guid postId = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + CreateRatingServiceModel createRatingServiceModel = new CreateRatingServiceModel + { + PostId = postId, + UserId = userId, + IsLike = isLike + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike + }; + User user = new User + { + Id = userId + }; + Post post = new Post + { + Id = postId + }; + + this._postRepositoryMock + .Setup(p => p.DoesPostExist(It.IsAny<Guid>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.UserRatedPost(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(false); + this._userRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(user); + this._postRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(post); + this._ratingRepositoryMock + .Setup(p => p.AddAsync(It.IsAny<Rating>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(rating); + this._mapperMock + .Setup(p => p.Map<Rating>(It.IsAny<CreateRatingServiceModel>())) + .Returns(rating); + + Guid result = await this._ratingService.RatePost(createRatingServiceModel); + + Assert.AreEqual(id, result); + } + + [Test] + public async Task RatePost_ReturnsEmptyGuid_WhenEntityIsNotAddedSuccessfully() + { + bool isLike = true; + Guid id = Guid.NewGuid(); + Guid postId = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + CreateRatingServiceModel createRatingServiceModel = new CreateRatingServiceModel + { + PostId = postId, + UserId = userId, + IsLike = isLike + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike + }; + User user = new User + { + Id = userId + }; + Post post = new Post + { + Id = postId + }; + + this._postRepositoryMock + .Setup(p => p.DoesPostExist(It.IsAny<Guid>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.UserRatedPost(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(false); + this._userRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(user); + this._postRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(post); + this._ratingRepositoryMock + .Setup(p => p.AddAsync(It.IsAny<Rating>())) + .ReturnsAsync(false); + this._mapperMock + .Setup(p => p.Map<Rating>(It.IsAny<CreateRatingServiceModel>())) + .Returns(rating); + + Guid result = await this._ratingService.RatePost(createRatingServiceModel); + + Assert.AreEqual(result, Guid.Empty); + } + #endregion + + #region Read + [Test] + public async Task GetRatingById_ReturnsTheRating_WhenItExists() + { + Guid id = Guid.NewGuid(); + bool isLike = true; + User user = new User + { + Id = Guid.NewGuid() + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike, + User = user + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + IsLike = isLike + }; + + this._ratingRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(rating); + this._mapperMock + .Setup(p => p.Map<ReadRatingServiceModel>(It.IsAny<Rating>())) + .Returns(readRatingServiceModel); + + ReadRatingServiceModel result = await this._ratingService.GetRatingById(id); + + Assert.AreEqual(isLike, result.IsLike); + } + + [Test] + public void GetRatingById_ThrowsException_WhenRatingDoesNotExist() + { + string exceptionMessage = "The rating does not exist"; + this._ratingRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .Returns(Task.FromResult<Rating>(null)); + + Exception ex = Assert.ThrowsAsync<ArgumentException>(() => this._ratingService.GetRatingById(Guid.Empty)); + + Assert.AreEqual(exceptionMessage, ex.Message, "Incorecct exception message"); + } + + [Test] + public async Task GetRatingByPostAndUser_ReturnsTheRating_WhenItExists() + { + Guid id = Guid.NewGuid(); + bool isLike = true; + User user = new User + { + Id = Guid.NewGuid() + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike, + User = user + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + IsLike = isLike + }; + + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(rating); + this._mapperMock + .Setup(p => p.Map<ReadRatingServiceModel>(It.IsAny<Rating>())) + .Returns(readRatingServiceModel); + + ReadRatingServiceModel result = await this._ratingService.GetRatingByPostAndUser(user.Id, Guid.Empty); + + Assert.AreEqual(isLike, result.IsLike); + } + + [Test] + public void GetRatingByPostAndUser_ThrowsException_WhenRatingDoesNotExist() + { + string exceptionMessage = "The rating does not exist"; + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .Returns(Task.FromResult<Rating>(null)); + + Exception ex = Assert.ThrowsAsync<ArgumentException>(() => this._ratingService.GetRatingById(Guid.Empty)); + + Assert.AreEqual(exceptionMessage, ex.Message, "Incorecct exception message"); + } + #endregion + + #region Update + [Test] + public async Task UpdateRating_ReturnsObject_WhenRatingIsUpdatedSuccessfully() + { + Guid id = Guid.NewGuid(); + bool isLike = true; + UpdateRatingServiceModel updateRatingServiceModel = new UpdateRatingServiceModel + { + Id = id, + IsLike = isLike + }; + User user = new User + { + Id = Guid.NewGuid() + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike, + User = user + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + IsLike = isLike + }; + + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(rating); + this._userRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(user); + this._ratingRepositoryMock + .Setup(p => p.UserRatedPost(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.EditAsync(It.IsAny<Guid>(), It.IsAny<Rating>())) + .ReturnsAsync(true); + this._mapperMock + .Setup(p => p.Map<ReadRatingServiceModel>(It.IsAny<Rating>())) + .Returns(readRatingServiceModel); + + ReadRatingServiceModel result = await this._ratingService.UpdateRating(updateRatingServiceModel); + + Assert.AreEqual(result, readRatingServiceModel); + } + + [Test] + public async Task UpdateRating_ReturnsNull_WhenRatingIsNotUpdatedSuccessfully() + { + Guid id = Guid.NewGuid(); + bool isLike = true; + UpdateRatingServiceModel updateRatingServiceModel = new UpdateRatingServiceModel + { + Id = id, + IsLike = isLike + }; + User user = new User + { + Id = Guid.NewGuid() + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike, + User = user + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + IsLike = isLike + }; + + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(rating); + this._userRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(user); + this._ratingRepositoryMock + .Setup(p => p.UserRatedPost(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.EditAsync(It.IsAny<Guid>(), It.IsAny<Rating>())) + .ReturnsAsync(false); + + ReadRatingServiceModel result = await this._ratingService.UpdateRating(updateRatingServiceModel); + + Assert.IsNull(result); + } + + [Test] + public void UpdateRating_ThrowsException_WhenRatingDoesNotExists() + { + string exceptionMessage = "Rating does not exist!"; + UpdateRatingServiceModel updateRatingServiceModel = new UpdateRatingServiceModel + { + Id = Guid.Empty, + IsLike = true + }; + + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .Returns(Task.FromResult<Rating>(null)); + + Exception ex = Assert.ThrowsAsync<ArgumentException>(() => this._ratingService.UpdateRating(updateRatingServiceModel)); + + Assert.AreEqual(ex.Message, exceptionMessage); + } + + [Test] + public void UpdateRating_ThrowsException_WhenUserHasNotRatedPost() + { + string exceptionMessage = "User has not rated the post!"; + Guid id = Guid.NewGuid(); + bool isLike = true; + UpdateRatingServiceModel updateRatingServiceModel = new UpdateRatingServiceModel + { + Id = id, + IsLike = isLike + }; + User user = new User + { + Id = Guid.NewGuid() + }; + Rating rating = new Rating + { + Id = id, + IsLike = isLike, + User = user + }; + + this._ratingRepositoryMock + .Setup(p => p.GetRatingByUserAndPostId(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(rating); + this._userRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .ReturnsAsync(user); + this._ratingRepositoryMock + .Setup(p => p.UserRatedPost(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(false); + + Exception ex = Assert.ThrowsAsync<ArgumentException>(() => this._ratingService.UpdateRating(updateRatingServiceModel)); + + Assert.AreEqual(ex.Message, exceptionMessage); + } + #endregion + + #region Delete + [Test] + public async Task DeleteRating_ReturnsTrue_WhenRatingIsDeletedSuccessfully() + { + Guid ratingId = Guid.NewGuid(); + Rating rating = new Rating + { + Id = ratingId + }; + + this._ratingRepositoryMock + .Setup(p => p.DoesRatingExist(It.IsAny<Guid>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .Returns(Task.FromResult<Rating>(null)); + this._ratingRepositoryMock + .Setup(p => p.DeleteAsync(It.IsAny<Rating>())) + .ReturnsAsync(true); + + bool result = await this._ratingService.DeleteRating(ratingId); + + Assert.IsTrue(result); + } + + [Test] + public async Task DeleteRating_ReturnsFalse_WhenRatingIsNotDeletedSuccessfully() + { + Guid ratingId = Guid.NewGuid(); + Rating rating = new Rating + { + Id = ratingId + }; + + this._ratingRepositoryMock + .Setup(p => p.DoesRatingExist(It.IsAny<Guid>())) + .ReturnsAsync(true); + this._ratingRepositoryMock + .Setup(p => p.GetByIdAsync(It.IsAny<Guid>())) + .Returns(Task.FromResult<Rating>(null)); + this._ratingRepositoryMock + .Setup(p => p.DeleteAsync(It.IsAny<Rating>())) + .ReturnsAsync(false); + + bool result = await this._ratingService.DeleteRating(ratingId); + + Assert.IsFalse(result); + } + + [Test] + public void DeleteRating_ThrowsException_WhenRatingDoesNotExist() + { + string exceptionMessage = "Rating does not exist!"; + + this._ratingRepositoryMock + .Setup(p => p.DoesRatingExist(It.IsAny<Guid>())) + .ReturnsAsync(false); + + Exception ex = Assert.ThrowsAsync<ArgumentException>(() => this._ratingService.DeleteRating(Guid.Empty)); + + Assert.AreEqual(ex.Message, exceptionMessage); + } + #endregion + } +} diff --git a/src/Services/DevHive.Services/Configurations/Mapping/RatingMappings.cs b/src/Services/DevHive.Services/Configurations/Mapping/RatingMappings.cs index 4534511..9ad5f25 100644 --- a/src/Services/DevHive.Services/Configurations/Mapping/RatingMappings.cs +++ b/src/Services/DevHive.Services/Configurations/Mapping/RatingMappings.cs @@ -1,6 +1,6 @@ using AutoMapper; using DevHive.Data.Models; -using DevHive.Services.Models.Post.Rating; +using DevHive.Services.Models.Rating; namespace DevHive.Services.Configurations.Mapping { diff --git a/src/Services/DevHive.Services/Interfaces/IRatingService.cs b/src/Services/DevHive.Services/Interfaces/IRatingService.cs index beea821..be33300 100644 --- a/src/Services/DevHive.Services/Interfaces/IRatingService.cs +++ b/src/Services/DevHive.Services/Interfaces/IRatingService.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; using DevHive.Data.Models; -using DevHive.Services.Models.Post.Rating; +using DevHive.Services.Models.Rating; namespace DevHive.Services.Interfaces { @@ -16,7 +16,5 @@ namespace DevHive.Services.Interfaces Task<ReadRatingServiceModel> UpdateRating(UpdateRatingServiceModel updateRatingServiceModel); Task<bool> DeleteRating(Guid ratingId); - - Task<bool> HasUserRatedThisPost(Guid userId, Guid postId); } } diff --git a/src/Services/DevHive.Services/Services/PostService.cs b/src/Services/DevHive.Services/Services/PostService.cs index a3d5117..a565473 100644 --- a/src/Services/DevHive.Services/Services/PostService.cs +++ b/src/Services/DevHive.Services/Services/PostService.cs @@ -76,11 +76,21 @@ namespace DevHive.Services.Services User user = await this._userRepository.GetByIdAsync(post.Creator.Id) ?? throw new ArgumentException("The user does not exist!"); + int currentRating = 0; + foreach (Rating rating in post.Ratings) + { + if (rating.IsLike) + currentRating++; + else + currentRating--; + } + ReadPostServiceModel readPostServiceModel = this._postMapper.Map<ReadPostServiceModel>(post); readPostServiceModel.CreatorFirstName = user.FirstName; readPostServiceModel.CreatorLastName = user.LastName; readPostServiceModel.CreatorUsername = user.UserName; readPostServiceModel.FileUrls = post.Attachments.Select(x => x.FileUrl).ToList(); + readPostServiceModel.CurrentRating = currentRating; return readPostServiceModel; } diff --git a/src/Services/DevHive.Services/Services/RatingService.cs b/src/Services/DevHive.Services/Services/RatingService.cs index 6ddba1c..1f77a6e 100644 --- a/src/Services/DevHive.Services/Services/RatingService.cs +++ b/src/Services/DevHive.Services/Services/RatingService.cs @@ -8,7 +8,7 @@ using AutoMapper; using DevHive.Data.Interfaces; using DevHive.Data.Models; using DevHive.Services.Interfaces; -using DevHive.Services.Models.Post.Rating; +using DevHive.Services.Models.Rating; namespace DevHive.Services.Services { @@ -81,7 +81,7 @@ namespace DevHive.Services.Services #region Update public async Task<ReadRatingServiceModel> UpdateRating(UpdateRatingServiceModel updateRatingServiceModel) { - Rating rating = await this._ratingRepository.GetByIdAsync(updateRatingServiceModel.Id) ?? + Rating rating = await this._ratingRepository.GetRatingByUserAndPostId(updateRatingServiceModel.UserId, updateRatingServiceModel.PostId) ?? throw new ArgumentException("Rating does not exist!"); User user = await this._userRepository.GetByIdAsync(updateRatingServiceModel.UserId) ?? @@ -115,11 +115,5 @@ namespace DevHive.Services.Services return await this._ratingRepository.DeleteAsync(rating); } #endregion - - public async Task<bool> HasUserRatedThisPost(Guid userId, Guid postId) - { - return await this._ratingRepository - .UserRatedPost(userId, postId); - } } } diff --git a/src/Web/DevHive.Web.Models/Rating/UpdateRatingWebModel.cs b/src/Web/DevHive.Web.Models/Rating/UpdateRatingWebModel.cs index 425c3e1..176c099 100644 --- a/src/Web/DevHive.Web.Models/Rating/UpdateRatingWebModel.cs +++ b/src/Web/DevHive.Web.Models/Rating/UpdateRatingWebModel.cs @@ -8,10 +8,6 @@ namespace DevHive.Web.Models.Rating { public class UpdateRatingWebModel { - public Guid Id { get; set; } - - public Guid PostId { get; set; } - public bool IsLike { get; set; } } } diff --git a/src/Web/DevHive.Web.Tests/RatingController.Tests.cs b/src/Web/DevHive.Web.Tests/RatingController.Tests.cs new file mode 100644 index 0000000..c7340a6 --- /dev/null +++ b/src/Web/DevHive.Web.Tests/RatingController.Tests.cs @@ -0,0 +1,299 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using AutoMapper; +using DevHive.Common.Jwt.Interfaces; +using DevHive.Services.Interfaces; +using DevHive.Services.Models.Rating; +using DevHive.Web.Controllers; +using DevHive.Web.Models.Rating; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; + +namespace DevHive.Web.Tests +{ + [TestFixture] + public class RatingControllerTests + { + private Mock<IRatingService> _ratingServiceMock; + private Mock<IMapper> _mapperMock; + private Mock<IJwtService> _jwtServiceMock; + private RatingController _ratingController; + + [SetUp] + public void SetUp() + { + this._ratingServiceMock = new Mock<IRatingService>(); + this._mapperMock = new Mock<IMapper>(); + this._jwtServiceMock = new Mock<IJwtService>(); + this._ratingController = new RatingController(this._ratingServiceMock.Object, this._mapperMock.Object, this._jwtServiceMock.Object); + } + + #region Create + [Test] + public void CreateRating_ReturnsOkObjectResult_WhenRatingIsSuccessfullyCreated() + { + Guid postId = Guid.NewGuid(); + CreateRatingWebModel createRatingWebModel = new CreateRatingWebModel + { + PostId = postId, + IsLike = true + }; + CreateRatingServiceModel createRatingServiceModel = new CreateRatingServiceModel + { + PostId = postId, + IsLike = true + }; + Guid ratingId = Guid.NewGuid(); + + this._jwtServiceMock + .Setup(p => p.ValidateToken(It.IsAny<Guid>(), It.IsAny<string>())) + .Returns(true); + this._mapperMock + .Setup(p => p.Map<CreateRatingServiceModel>(It.IsAny<CreateRatingWebModel>())) + .Returns(createRatingServiceModel); + this._ratingServiceMock + .Setup(p => p.RatePost(It.IsAny<CreateRatingServiceModel>())) + .ReturnsAsync(ratingId); + + IActionResult result = this._ratingController.RatePost(Guid.Empty, createRatingWebModel, String.Empty).Result; + + Assert.IsInstanceOf<OkObjectResult>(result); + + var splitted = (result as OkObjectResult).Value + .ToString() + .Split('{', '}', '=', ' ') + .Where(x => !string.IsNullOrEmpty(x)) + .ToArray(); + + Guid resultId = Guid.Parse(splitted[1]); + + Assert.AreEqual(ratingId, resultId); + } + + [Test] + public void CreateRating_ReturnsBadRequestResult_WhenRatingIsNotSuccessfullyCreated() + { + Guid postId = Guid.NewGuid(); + CreateRatingWebModel createRatingWebModel = new CreateRatingWebModel + { + PostId = postId, + IsLike = true + }; + CreateRatingServiceModel createRatingServiceModel = new CreateRatingServiceModel + { + PostId = postId, + IsLike = true + }; + Guid ratingId = Guid.NewGuid(); + + this._jwtServiceMock + .Setup(p => p.ValidateToken(It.IsAny<Guid>(), It.IsAny<string>())) + .Returns(true); + this._mapperMock + .Setup(p => p.Map<CreateRatingServiceModel>(It.IsAny<CreateRatingWebModel>())) + .Returns(createRatingServiceModel); + this._ratingServiceMock + .Setup(p => p.RatePost(It.IsAny<CreateRatingServiceModel>())) + .ReturnsAsync(Guid.Empty); + + IActionResult result = this._ratingController.RatePost(Guid.Empty, createRatingWebModel, String.Empty).Result; + + Assert.IsInstanceOf<BadRequestResult>(result); + } + #endregion + + #region Read + [Test] + public void GetRatingById_ReturnsTheRating_WhenItExists() + { + Guid id = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + Guid postId = Guid.NewGuid(); + ReadRatingWebModel readRatingWebModel = new ReadRatingWebModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + + this._mapperMock + .Setup(p => p.Map<ReadRatingServiceModel>(It.IsAny<ReadRatingWebModel>())) + .Returns(readRatingServiceModel); + this._ratingServiceMock + .Setup(p => p.GetRatingById(It.IsAny<Guid>())) + .ReturnsAsync(readRatingServiceModel); + + IActionResult result = this._ratingController.GetRatingById(id).Result; + + Assert.IsInstanceOf<OkObjectResult>(result); + } + + [Test] + public void GetRatingByUserAndPost_ReturnsTheRating_WhenItExists() + { + Guid id = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + Guid postId = Guid.NewGuid(); + ReadRatingWebModel readRatingWebModel = new ReadRatingWebModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + + this._mapperMock + .Setup(p => p.Map<ReadRatingServiceModel>(It.IsAny<ReadRatingWebModel>())) + .Returns(readRatingServiceModel); + this._ratingServiceMock + .Setup(p => p.GetRatingByPostAndUser(It.IsAny<Guid>(), It.IsAny<Guid>())) + .ReturnsAsync(readRatingServiceModel); + + IActionResult result = this._ratingController.GetRatingByUserAndPost(userId, postId).Result; + + Assert.IsInstanceOf<OkObjectResult>(result); + } + + #endregion + + #region Update + [Test] + public void Update_ShouldReturnOkResult_WhenRatingIsUpdatedSuccessfully() + { + Guid id = Guid.NewGuid(); + Guid userId = Guid.NewGuid(); + Guid postId = Guid.NewGuid(); + UpdateRatingWebModel updateRatingWebModel = new UpdateRatingWebModel + { + IsLike = true + }; + UpdateRatingServiceModel updateRatingServiceModel = new UpdateRatingServiceModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + ReadRatingWebModel readRatingWebModel = new ReadRatingWebModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + ReadRatingServiceModel readRatingServiceModel = new ReadRatingServiceModel + { + Id = id, + UserId = userId, + PostId = postId, + IsLike = true + }; + + this._jwtServiceMock + .Setup(p => p.ValidateToken(It.IsAny<Guid>(), It.IsAny<string>())) + .Returns(true); + this._mapperMock + .Setup(p => p.Map<UpdateRatingServiceModel>(It.IsAny<UpdateRatingWebModel>())) + .Returns(updateRatingServiceModel); + this._mapperMock + .Setup(p => p.Map<ReadRatingWebModel>(It.IsAny<ReadRatingServiceModel>())) + .Returns(readRatingWebModel); + this._ratingServiceMock + .Setup(p => p.UpdateRating(It.IsAny<UpdateRatingServiceModel>())) + .ReturnsAsync(readRatingServiceModel); + + IActionResult result = this._ratingController.UpdateRating(userId, postId, updateRatingWebModel, String.Empty).Result; + + Assert.IsInstanceOf<OkObjectResult>(result); + } + + [Test] + public void Update_ShouldReturnBadObjectResult_WhenLanguageIsNotUpdatedSuccessfully() + { + Guid id = Guid.NewGuid(); + UpdateRatingWebModel updateRatingWebModel = new UpdateRatingWebModel + { + IsLike = true + }; + UpdateRatingServiceModel updateRatingServiceModel = new UpdateRatingServiceModel + { + Id = id, + IsLike = true + }; + + this._jwtServiceMock + .Setup(p => p.ValidateToken(It.IsAny<Guid>(), It.IsAny<string>())) + .Returns(true); + this._mapperMock + .Setup(p => p.Map<UpdateRatingServiceModel>(It.IsAny<UpdateRatingWebModel>())) + .Returns(updateRatingServiceModel); + this._ratingServiceMock + .Setup(p => p.UpdateRating(It.IsAny<UpdateRatingServiceModel>())) + .Returns(Task.FromResult<ReadRatingServiceModel>(null)); + + IActionResult result = this._ratingController.UpdateRating(Guid.Empty, Guid.Empty, updateRatingWebModel, String.Empty).Result; + + Assert.IsInstanceOf<BadRequestResult>(result); + } + #endregion + + #region Delete + [Test] + public void Delete_ReturnsOkResult_WhenRatingIsDeletedSuccessfully() + { + Guid id = Guid.NewGuid(); + + this._jwtServiceMock + .Setup(p => p.ValidateToken(It.IsAny<Guid>(), It.IsAny<string>())) + .Returns(true); + this._ratingServiceMock + .Setup(p => p.DeleteRating(It.IsAny<Guid>())) + .ReturnsAsync(true); + + IActionResult result = this._ratingController.DeleteRating(Guid.Empty, Guid.Empty, String.Empty).Result; + + Assert.IsInstanceOf<OkResult>(result); + } + + [Test] + public void Delete_ReturnsBadRequestObjectResult_WhenRatingIsNotDeletedSuccessfully() + { + string message = "Could not delete Rating"; + Guid id = Guid.NewGuid(); + + this._jwtServiceMock + .Setup(p => p.ValidateToken(It.IsAny<Guid>(), It.IsAny<string>())) + .Returns(true); + this._ratingServiceMock + .Setup(p => p.DeleteRating(It.IsAny<Guid>())) + .ReturnsAsync(false); + + IActionResult result = this._ratingController.DeleteRating(Guid.Empty, Guid.Empty, String.Empty).Result; + + Assert.IsInstanceOf<BadRequestObjectResult>(result); + + BadRequestObjectResult badRequestObjectResult = result as BadRequestObjectResult; + string resultModel = badRequestObjectResult.Value.ToString(); + + Assert.AreEqual(message, resultModel); + } + #endregion + } +} diff --git a/src/Web/DevHive.Web/Configurations/Mapping/RatingMappings.cs b/src/Web/DevHive.Web/Configurations/Mapping/RatingMappings.cs index 23c3eeb..1d731d8 100644 --- a/src/Web/DevHive.Web/Configurations/Mapping/RatingMappings.cs +++ b/src/Web/DevHive.Web/Configurations/Mapping/RatingMappings.cs @@ -1,5 +1,5 @@ using AutoMapper; -using DevHive.Services.Models.Post.Rating; +using DevHive.Services.Models.Rating; using DevHive.Web.Models.Rating; namespace DevHive.Web.Configurations.Mapping diff --git a/src/Web/DevHive.Web/Controllers/RatingController.cs b/src/Web/DevHive.Web/Controllers/RatingController.cs index 5716b85..7d21795 100644 --- a/src/Web/DevHive.Web/Controllers/RatingController.cs +++ b/src/Web/DevHive.Web/Controllers/RatingController.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using AutoMapper; using DevHive.Common.Jwt.Interfaces; using DevHive.Services.Interfaces; -using DevHive.Services.Models.Post.Rating; +using DevHive.Services.Models.Rating; using DevHive.Web.Models.Rating; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -11,19 +11,17 @@ using Microsoft.AspNetCore.Mvc; namespace DevHive.Web.Controllers { [ApiController] - //[Authorize(Roles = "Admin,User")] + [Authorize(Roles = "Admin,User")] [Route("api/[controller]")] public class RatingController { private readonly IRatingService _rateService; - private readonly IUserService _userService; private readonly IMapper _mapper; private readonly IJwtService _jwtService; - public RatingController(IRatingService rateService, IUserService userService, IMapper mapper, IJwtService jwtService) + public RatingController(IRatingService rateService, IMapper mapper, IJwtService jwtService) { this._rateService = rateService; - this._userService = userService; this._mapper = mapper; this._jwtService = jwtService; } @@ -65,7 +63,7 @@ namespace DevHive.Web.Controllers } [HttpPut] - public async Task<IActionResult> UpdateRating(Guid userId, [FromBody] UpdateRatingWebModel updateRatingWebModel, [FromHeader] string authorization) + public async Task<IActionResult> UpdateRating(Guid userId, Guid postId, [FromBody] UpdateRatingWebModel updateRatingWebModel, [FromHeader] string authorization) { if (!this._jwtService.ValidateToken(userId, authorization)) return new UnauthorizedResult(); @@ -73,6 +71,7 @@ namespace DevHive.Web.Controllers UpdateRatingServiceModel updateRatingServiceModel = this._mapper.Map<UpdateRatingServiceModel>(updateRatingWebModel); updateRatingServiceModel.UserId = userId; + updateRatingServiceModel.PostId = postId; ReadRatingServiceModel readRatingServiceModel = await this._rateService.UpdateRating(updateRatingServiceModel); @@ -86,7 +85,7 @@ namespace DevHive.Web.Controllers } [HttpDelete] - public async Task<IActionResult> DeleteTating(Guid userId, Guid ratingId, [FromHeader] string authorization) + public async Task<IActionResult> DeleteRating(Guid userId, Guid ratingId, [FromHeader] string authorization) { if (!this._jwtService.ValidateToken(userId, authorization)) return new UnauthorizedResult(); diff --git a/src/Web/DevHive.Web/Startup.cs b/src/Web/DevHive.Web/Startup.cs index ebd091e..002c718 100644 --- a/src/Web/DevHive.Web/Startup.cs +++ b/src/Web/DevHive.Web/Startup.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using DevHive.Web.Configurations.Extensions; using Newtonsoft.Json; -using System.Threading.Tasks; namespace DevHive.Web { |
