diff --git a/ShoppingAssistantApi.Persistance/Database/MongoDbContext.cs b/ShoppingAssistantApi.Persistance/Database/MongoDbContext.cs index ea3f3a3..ac3876e 100644 --- a/ShoppingAssistantApi.Persistance/Database/MongoDbContext.cs +++ b/ShoppingAssistantApi.Persistance/Database/MongoDbContext.cs @@ -16,4 +16,6 @@ public class MongoDbContext } public IMongoDatabase Db => this._db; + + public MongoClient Client => this._client; } \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/ShoppingAssistantApi.Tests.csproj b/ShoppingAssistantApi.Tests/ShoppingAssistantApi.Tests.csproj index a7e4074..c36f3b4 100644 --- a/ShoppingAssistantApi.Tests/ShoppingAssistantApi.Tests.csproj +++ b/ShoppingAssistantApi.Tests/ShoppingAssistantApi.Tests.csproj @@ -10,7 +10,6 @@ - diff --git a/ShoppingAssistantApi.Tests/TestExtentions/AccessExtention.cs b/ShoppingAssistantApi.Tests/TestExtentions/AccessExtention.cs deleted file mode 100644 index 16e0a03..0000000 --- a/ShoppingAssistantApi.Tests/TestExtentions/AccessExtention.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Text; -using Newtonsoft.Json; -using ShoppingAssistantApi.Application.Models.Identity; - -namespace ShoppingAssistantApi.Tests.TestExtentions; - -public static class AccessExtention -{ - public static async Task Login(string email, string password, HttpClient httpClient) - { - var mutation = new - { - query = "mutation Login($login: AccessUserModelInput!) { login(login: $login) { accessToken refreshToken }}", - variables = new - { - login = new - { - email = email, - password = password - } - } - }; - - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await httpClient.PostAsync("graphql", content); - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - return new TokensModel - { - AccessToken = (string)document.data.login.accessToken, - RefreshToken = (string)document.data.login.refreshToken - }; - } - - public static async Task CreateGuest(string guestId, HttpClient httpClient) - { - var mutation = new - { - query = "mutation AccessGuest($guest: AccessGuestModelInput!) { accessGuest(guest: $guest) { accessToken, refreshToken } }", - variables = new - { - guest = new - { - guestId - } - } - }; - - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await httpClient.PostAsync("graphql", content); - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - return new TokensModel - { - AccessToken = (string)document.data.accessGuest.accessToken, - RefreshToken = (string)document.data.accessGuest.refreshToken - }; - } -} \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/TestExtentions/DbInitializer.cs b/ShoppingAssistantApi.Tests/TestExtentions/DbInitializer.cs new file mode 100644 index 0000000..ae2ed20 --- /dev/null +++ b/ShoppingAssistantApi.Tests/TestExtentions/DbInitializer.cs @@ -0,0 +1,140 @@ +using Microsoft.Extensions.Logging; +using MongoDB.Bson; +using ShoppingAssistantApi.Domain.Entities; +using ShoppingAssistantApi.Domain.Enums; +using ShoppingAssistantApi.Infrastructure.Services.Identity; +using ShoppingAssistantApi.Persistance.Database; + +namespace ShoppingAssistantApi.Tests.TestExtentions; + +public class DbInitializer +{ + private readonly MongoDbContext _dbContext; + + public DbInitializer(MongoDbContext dbContext) + { + _dbContext = dbContext; + } + + public void InitializeDb() + { + _dbContext.Client.DropDatabase(_dbContext.Db.DatabaseNamespace.DatabaseName); + + InitializeUsersAsync().Wait(); + InitializeWishlistsAsync().Wait(); + } + + public async Task InitializeUsersAsync() + { + #region Roles + + var rolesCollection = _dbContext.Db.GetCollection("Roles"); + + var questRole = new Role + { + Name = "Guest" + }; + await rolesCollection.InsertOneAsync(questRole); + + var userRole = new Role + { + Name = "User" + }; + await rolesCollection.InsertOneAsync(userRole); + + var adminRole = new Role + { + Name = "Admin" + }; + await rolesCollection.InsertOneAsync(adminRole); + + #endregion + + #region Users + + var passwordHasher = new PasswordHasher(new Logger(new LoggerFactory())); + var usersCollection = _dbContext.Db.GetCollection("Users"); + + var testUser = new User + { + Id = ObjectId.Parse("652c3b89ae02a3135d6409fc"), + Email = "test@gmail.com", + Phone = "+380953326869", + Roles = new List { questRole, userRole }, + PasswordHash = passwordHasher.Hash("Yuiop12345"), + CreatedById = ObjectId.Empty, + CreatedDateUtc = DateTime.UtcNow + }; + await usersCollection.InsertOneAsync(testUser); + + var adminUser = new User + { + Id = ObjectId.Parse("652c3b89ae02a3135d6408fc"), + Email = "admin@gmail.com", + Phone = "+12345678901", + Roles = new List { questRole, userRole, adminRole }, + PasswordHash = passwordHasher.Hash("Yuiop12345"), + CreatedById = ObjectId.Empty, + CreatedDateUtc = DateTime.UtcNow + }; + await usersCollection.InsertOneAsync(adminUser); + + var wishlistsUser = new User + { + Id = ObjectId.Parse("652c3b89ae02a3135d6418fc"), + Email = "wishlists@gmail.com", + Phone = "+12234567890", + Roles = new List { questRole }, + PasswordHash = passwordHasher.Hash("Yuiop12345"), + CreatedById = ObjectId.Empty, + CreatedDateUtc = DateTime.UtcNow + }; + await usersCollection.InsertOneAsync(wishlistsUser); + + #endregion + } + + public async Task InitializeWishlistsAsync() + { + var wishlistsCollection = _dbContext.Db.GetCollection("Wishlists"); + + var gamingPcWishlist = new Wishlist + { + Id = ObjectId.Parse("ab79cde6f69abcd3efab65cd"), + Name = "Gaming PC", + Type = WishlistTypes.Product.ToString(), + CreatedById = ObjectId.Parse("652c3b89ae02a3135d6418fc"), + Messages = new Message[] + { + new Message + { + Text = "Prompt", + Role = MessageRoles.User.ToString(), + }, + new Message + { + Text = "Answer", + Role = MessageRoles.Application.ToString(), + }, + } + }; + await wishlistsCollection.InsertOneAsync(gamingPcWishlist); + + var genericWishlist = new Wishlist + { + Id = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"), + Name = "Generic Wishlist Name", + Type = WishlistTypes.Product.ToString(), + CreatedById = ObjectId.Parse("652c3b89ae02a3135d6409fc"), + Messages = new Message[] + { + new Message + { + Text = "Prompt", + Role = MessageRoles.User.ToString(), + } + } + }; + await wishlistsCollection.InsertOneAsync(genericWishlist); + } +} diff --git a/ShoppingAssistantApi.Tests/TestExtentions/TestingFactory.cs b/ShoppingAssistantApi.Tests/TestExtentions/TestingFactory.cs index a8407df..a63a957 100644 --- a/ShoppingAssistantApi.Tests/TestExtentions/TestingFactory.cs +++ b/ShoppingAssistantApi.Tests/TestExtentions/TestingFactory.cs @@ -1,48 +1,64 @@ -using Microsoft.AspNetCore.Hosting; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Mongo2Go; -using ShoppingAssistantApi.Persistance.PersistanceExtentions; +using ShoppingAssistantApi.Persistance.Database; namespace ShoppingAssistantApi.Tests.TestExtentions; public class TestingFactory : WebApplicationFactory where TEntryPoint : Program { - private readonly MongoDbRunner _runner = MongoDbRunner.Start(); + private MongoDbRunner? _runner; private bool _isDataInitialaized = false; protected override void ConfigureWebHost(IWebHostBuilder builder) { + // Mongo2Go is not supported on ARM64 so we need to use a real MongoDB instance + Console.WriteLine($"[ARCH]: {RuntimeInformation.ProcessArchitecture}"); + + var connectionString = string.Empty; + if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) + { + connectionString = "mongodb+srv://api:pUe2dLT8llwEgwzq@cluster0.3q6mxmw.mongodb.net/?retryWrites=true&w=majority"; + } + else + { + _runner = MongoDbRunner.Start(); + connectionString = _runner.ConnectionString; + } + builder.ConfigureAppConfiguration((context, config) => { - var dbConfig = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary() - { - { "ConnectionStrings:MongoDb", _runner.ConnectionString } - }) - .Build(); + var dbConfig = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary() + { + { "ConnectionStrings:MongoDb", connectionString } + }) + .Build(); config.AddConfiguration(dbConfig); }); } - public async Task InitialaizeData() + public void InitialaizeDatabase() { - if (!_isDataInitialaized) - { - _isDataInitialaized = true; - using var scope = Services.CreateScope(); - var initialaizer = new DbInitialaizer(scope.ServiceProvider); - using var cancellationTokenSource = new CancellationTokenSource(); - var cancellationToken = cancellationTokenSource.Token; - await initialaizer.InitialaizeDb(cancellationToken); - } + if (_isDataInitialaized) return; + + using var scope = Services.CreateScope(); + var mongodbContext = scope.ServiceProvider.GetRequiredService(); + + var initialaizer = new DbInitializer(mongodbContext); + initialaizer.InitializeDb(); + + _isDataInitialaized = true; } protected override void Dispose(bool disposing) { - _runner.Dispose(); + _runner?.Dispose(); base.Dispose(disposing); } } \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/TestExtentions/UserExtention.cs b/ShoppingAssistantApi.Tests/TestExtentions/UserExtention.cs deleted file mode 100644 index 269ff8a..0000000 --- a/ShoppingAssistantApi.Tests/TestExtentions/UserExtention.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Net.Http.Headers; -using System.Text; -using Newtonsoft.Json; -using ShoppingAssistantApi.Application.Models.Dtos; - -namespace ShoppingAssistantApi.Tests.TestExtentions; - -public static class UserExtention -{ - public static async Task GetCurrentUser(HttpClient httpClient) - { - var query = new - { - query = "query CurrentUser { currentUser { id, guestId, phone, email, refreshToken, refreshTokenExpiryDate, roles { id, name }}}", - variables = new { } - }; - - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await httpClient.PostAsync("graphql", content); - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - return JsonConvert.DeserializeObject(document.data.currentUser.ToString()); - } - - public static async Task> GetUsers(int amount, HttpClient httpClient) - { - var accessToken = await AccessExtention.Login("mykhailo.bilodid@nure.ua", "Yuiop12345", httpClient); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.AccessToken); - - var query = new - { - query = "query UsersPage($pageNumber: Int!, $pageSize: Int!) { usersPage(pageNumber: $pageNumber, pageSize: $pageSize) { items { id, email, phone }}}", - variables = new - { - pageNumber = 1, - pageSize = amount - } - }; - - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await httpClient.PostAsync("graphql", content); - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - return JsonConvert.DeserializeObject>(document.data.usersPage.items.ToString()); - } -} \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/Tests/AccessTests.cs b/ShoppingAssistantApi.Tests/Tests/AccessTests.cs index 65f29f4..74f6cc1 100644 --- a/ShoppingAssistantApi.Tests/Tests/AccessTests.cs +++ b/ShoppingAssistantApi.Tests/Tests/AccessTests.cs @@ -1,26 +1,21 @@ -using System.Net; -using System.Text; -using Xunit; +using Newtonsoft.Json.Linq; +using ShoppingAssistantApi.Application.Models.Identity; using ShoppingAssistantApi.Tests.TestExtentions; -using Newtonsoft.Json; +using Xunit; namespace ShoppingAssistantApi.Tests.Tests; -[Collection("Tests")] - -public class AccessTests : IClassFixture> +// TODO: make errors test more descrptive +public class AccessTests : TestsBase { - private readonly HttpClient _httpClient; - public AccessTests(TestingFactory factory) - { - _httpClient = factory.CreateClient(); - factory.InitialaizeData().GetAwaiter().GetResult(); - } + : base(factory) + { } [Fact] public async Task AccessGuestAsync_ValidGuid_ReturnsTokensModel() { + // Arrange var mutation = new { query = "mutation AccessGuest($guest: AccessGuestModelInput!) { accessGuest(guest: $guest) { accessToken, refreshToken } }", @@ -33,27 +28,20 @@ public class AccessTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + // Act + var jsonObject = await SendGraphQlRequestAsync(mutation); + var tokens = (TokensModel?) jsonObject?.data?.accessGuest?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessToken = (string)document.data.accessGuest.accessToken; - var refreshToken = (string)document.data.accessGuest.refreshToken; - - Assert.NotNull(accessToken); - Assert.NotNull(refreshToken); - } + // Assert + Assert.NotNull(tokens); + Assert.NotNull(tokens.AccessToken); + Assert.NotNull(tokens.RefreshToken); + } [Theory] - [InlineData("")] + [InlineData(null)] [InlineData("invalid-guid-format")] - public async Task AccessGuestAsync_InvalidGuid_ReturnsInternalServerError(string guestId) + public async Task AccessGuestAsync_InvalidGuid_ReturnsErrors(string guestId) { var mutation = new { @@ -67,19 +55,19 @@ public class AccessTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } [Theory] [InlineData("invalid-email-format", null, "Yuiop12345")] + [InlineData(null, "invalid-phone", "Yuiop12345")] + [InlineData("test@gmail.com", null, "random-password")] [InlineData(null, null, "Yuiop12345")] - [InlineData(null, null, "")] - [InlineData("mihail.beloded.work@gmail.com", null, "")] - public async Task LoginAsync_InvalidCredentials_ReturnsInternalServerError(string email, string phone, string password) + public async Task LoginAsync_InvalidCredentials_ReturnsErrors(string email, string phone, string password) { var mutation = new { @@ -95,17 +83,17 @@ public class AccessTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } - + [Theory] - [InlineData("mykhailo.bilodid@nure.ua", "+380953326869", "Yuiop12345")] - [InlineData(null, "+380953326888", "Yuiop12345")] - [InlineData("mykhailo.bilodid@nure.ua", null, "Yuiop12345")] + [InlineData("test@gmail.com", "+380953326869", "Yuiop12345")] + [InlineData(null, "+380953326869", "Yuiop12345")] + [InlineData("test@gmail.com", null, "Yuiop12345")] public async Task LoginAsync_ValidCredentials_ReturnsTokensModel(string email, string phone, string password) { var mutation = new @@ -121,83 +109,85 @@ public class AccessTests : IClassFixture> } } }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var tokens = (TokensModel?) jsonObject?.data?.login?.ToObject(); - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessToken = (string)document.data.login.accessToken; - var refreshToken = (string)document.data.login.refreshToken; - - Assert.NotNull(accessToken); - Assert.NotNull(refreshToken); + Assert.NotNull(tokens); + Assert.NotNull(tokens.AccessToken); + Assert.NotNull(tokens.RefreshToken); } [Fact] public async Task RefreshUserTokenAsync_ValidTokensModel_ReturnsTokensModel() { - var tokensModel = await AccessExtention.CreateGuest(new Guid().ToString(), _httpClient); - var accessToken = tokensModel.AccessToken; - var refreshToken = tokensModel.RefreshToken; - + var tokensModel = await CreateGuestAsync(); var mutation = new { - query = "mutation RefreshToken($model: TokensModelInput!) { refreshUserToken(model: $model) { accessToken refreshToken }}", + query = "mutation RefreshToken($model: TokensModelInput!) { refreshAccessToken(model: $model) { accessToken refreshToken }}", variables = new { model = new { - accessToken, - refreshToken + accessToken = tokensModel.AccessToken, + refreshToken = tokensModel.RefreshToken } } }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var tokens = (TokensModel?) jsonObject?.data?.refreshAccessToken?.ToObject(); - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessTokenResult = (string)document.data.refreshUserToken.accessToken; - var refreshTokenResult = (string)document.data.refreshUserToken.refreshToken; - - Assert.NotNull(accessTokenResult); - Assert.NotNull(refreshTokenResult); + Assert.NotNull(tokens); + Assert.NotNull(tokens.AccessToken); + Assert.NotNull(tokens.RefreshToken); } - [Theory] - [InlineData(null, null)] - [InlineData("invalid-access-token", "invalid-refresh-token")] - public async Task RefreshUserTokenAsync_InvalidTokensModel_ReturnsInternalServerError(string refreshToken, string accessToken) + [Fact] + public async Task RefreshAccessTokenAsync_NonExistingRefreshToken_ReturnsErrors() { var mutation = new { - query = "mutation RefreshToken($model: TokensModelInput!) { refreshUserToken(model: $model) { accessToken refreshToken }}", + query = "mutation RefreshToken($model: TokensModelInput!) { refreshAccessToken(model: $model) { accessToken refreshToken }}", variables = new { model = new { - accessToken, - refreshToken + accessToken = "random-access-token", + refreshToken = "random-refresh-token" } } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); + } + + private async Task CreateGuestAsync() + { + var mutation = new + { + query = @" + mutation AccessGuest($guest: AccessGuestModelInput!) { + accessGuest(guest: $guest) { + accessToken, refreshToken + } + }", + variables = new + { + guest = new + { + guestId = Guid.NewGuid() + } + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var tokens = (TokensModel?) jsonObject?.data?.accessGuest?.ToObject(); + + return tokens; } } \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/Tests/RolesTests.cs b/ShoppingAssistantApi.Tests/Tests/RolesTests.cs index 29b3774..2e52ef1 100644 --- a/ShoppingAssistantApi.Tests/Tests/RolesTests.cs +++ b/ShoppingAssistantApi.Tests/Tests/RolesTests.cs @@ -1,138 +1,42 @@ -using System.Net; -using System.Text; -using Xunit; -using ShoppingAssistantApi.Tests.TestExtentions; -using System.Net.Http.Headers; -using Newtonsoft.Json; -using GreenDonut; +using ShoppingAssistantApi.Tests.TestExtentions; +using Newtonsoft.Json.Linq; +using ShoppingAssistantApi.Application.Paging; +using ShoppingAssistantApi.Application.Models.Dtos; namespace ShoppingAssistantApi.Tests.Tests; -[Collection("Tests")] -public class RolesTests : IClassFixture> +// TODO: make errors test more descrptive +public class RolesTests : TestsBase { - private readonly HttpClient _httpClient; - public RolesTests(TestingFactory factory) + : base(factory) + { } + + [Fact] + public async Task AddRole_ValidName_ReturnsCreatedRole() { - _httpClient = factory.CreateClient(); - factory.InitialaizeData().GetAwaiter().GetResult(); + await LoginAsync("admin@gmail.com", "Yuiop12345"); + var mutation = new + { + query = "mutation AddRole ($dto: RoleCreateDtoInput!){ addRole (roleDto: $dto) { id, name }} ", + variables = new + { + dto = new + { + name = "NewRole" + } + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var role = jsonObject?.data?.addRole?.ToObject(); + + Assert.NotNull(role); + Assert.Equal("NewRole", role.Name); } [Fact] - public async Task AddToRoleAsync_ValidRoleName_ReturnsTokensModel() - { - var usersPage = await UserExtention.GetUsers(10, _httpClient); - var mutation = new - { - query = "mutation AddToRole($roleName: String!, $id: String!) { addToRole(roleName: $roleName, id: $id) { accessToken, refreshToken }}", - variables = new - { - roleName = "Admin", - id = usersPage[0].Id, - } - }; - - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessToken = (string)document.data.addToRole.accessToken; - var refreshToken = (string)document.data.addToRole.refreshToken; - - Assert.NotNull(accessToken); - Assert.NotNull(refreshToken); - } - - - [Theory] - [InlineData("")] - [InlineData("InvalidRole")] - public async Task AddToRoleAsync_InvalidRoleName_ReturnsInternalServerError(string roleName) - { - var usersPage = await UserExtention.GetUsers(10, _httpClient); - var mutation = new - { - query = "mutation AddToRole($roleName: String!, $id: String!) { addToRole(roleName: $roleName, id: $id) { accessToken, refreshToken }}", - variables = new - { - roleName, - id = usersPage[0].Id, - } - }; - - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - } - - - [Fact] - public async Task RemoveFromRoleAsync_ValidRoleName_ReturnsTokensModel() - { - var usersPage = await UserExtention.GetUsers(10, _httpClient); - var mutation = new - { - query = "mutation RemoveFromRole($roleName: String!, $id: String!) { removeFromRole(roleName: $roleName, id: $id) { accessToken, refreshToken }}", - variables = new - { - roleName = "Admin", - id = usersPage[0].Id, - } - }; - - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessToken = (string)document.data.removeFromRole.accessToken; - var refreshToken = (string)document.data.removeFromRole.refreshToken; - - Assert.NotNull(accessToken); - Assert.NotNull(refreshToken); - } - - [Theory] - [InlineData("")] - [InlineData("InvalidRole")] - public async Task RemoveFromRoleAsync_InvalidRoleName_ReturnsInternalServerError(string roleName) - { - var usersPage = await UserExtention.GetUsers(10, _httpClient); - var mutation = new - { - query = "mutation RemoveFromRole($roleName: String!, $id: String!) { removeFromRole(roleName: $roleName, id: $id) { accessToken, refreshToken }}", - variables = new - { - roleName, - id = usersPage[0].Id, - } - }; - - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - } - - [Theory] - [InlineData("User")] - [InlineData(null)] - public async Task AddRole_InvalidRoleName_ReturnsInternalServerError(string roleName) + public async Task AddRole_Unauthorized_ReturnsErrors() { var mutation = new { @@ -141,23 +45,45 @@ public class RolesTests : IClassFixture> { dto = new { - name = roleName + name = "NewRole" + } + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; + + Assert.NotNull(errors); + Assert.True(errors.Count > 0); + } + + [Fact] + public async Task AddRole_ExistingRoleName_ReturnsErrors() + { + await LoginAsync("admin@gmail.com", "Yuiop12345"); + var mutation = new + { + query = "mutation AddRole ($dto: RoleCreateDtoInput!){ addRole (roleDto: $dto) { id, name }} ", + variables = new + { + dto = new + { + name = "User" } } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } [Fact] public async Task GetRolesPageAsync_ValidPageNumberAndSize_ReturnsRolesPagedList() { - var tokensModel = await AccessExtention.Login("mykhailo.bilodid@nure.ua", "Yuiop12345", _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); + await LoginAsync("admin@gmail.com", "Yuiop12345"); var query = new { query = "query RolesPage($pageNumber: Int!, $pageSize: Int!) { rolesPage(pageNumber: $pageNumber, pageSize: $pageSize) { items { id, name } }}", @@ -167,18 +93,11 @@ public class RolesTests : IClassFixture> pageSize = 3 } }; + + var jsonObject = await SendGraphQlRequestAsync(query); + var pagedList = (PagedList?) jsonObject?.data?.rolesPage?.ToObject>(); - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); - - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var items = document.data.rolesPage.items; - Assert.NotEmpty(items); + Assert.NotNull(pagedList); + Assert.NotEmpty(pagedList.Items); } } \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/Tests/TestsBase.cs b/ShoppingAssistantApi.Tests/Tests/TestsBase.cs new file mode 100644 index 0000000..d5d7962 --- /dev/null +++ b/ShoppingAssistantApi.Tests/Tests/TestsBase.cs @@ -0,0 +1,66 @@ +using System.Net.Http.Headers; +using System.Text; +using Newtonsoft.Json; +using ShoppingAssistantApi.Application.Models.Dtos; +using ShoppingAssistantApi.Tests.TestExtentions; + +namespace ShoppingAssistantApi.Tests.Tests; + +public class TestsBase: IClassFixture> +{ + private protected HttpClient _httpClient; + + public TestsBase(TestingFactory factory) + { + _httpClient = factory.CreateClient(); + factory.InitialaizeDatabase(); + } + + public async Task LoginAsync(string email, string password) + { + var mutation = new + { + query = "mutation Login($login: AccessUserModelInput!) { login(login: $login) { accessToken refreshToken }}", + variables = new + { + login = new + { + email = email, + password = password + } + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", (string?) jsonObject?.data?.login?.accessToken); + } + + public async Task SendGraphQlRequestAsync(object request) + { + var jsonPayload = JsonConvert.SerializeObject(request); + var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + using var response = await _httpClient.PostAsync("graphql", content); + var responseString = await response.Content.ReadAsStringAsync(); + Console.WriteLine(responseString); + + var jsonObject = JsonConvert.DeserializeObject(responseString); + + return jsonObject; + } + + public async Task GetCurrentUserAsync() + { + var query = new + { + query = "query CurrentUser { currentUser { id, guestId, phone, email, roles { id, name }}}", + variables = new { } + }; + + var jsonObject = await SendGraphQlRequestAsync(query); + var user = (UserDto?) jsonObject?.data?.currentUser?.ToObject(); + + return user; + } +} \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/Tests/UsersTests.cs b/ShoppingAssistantApi.Tests/Tests/UsersTests.cs index 8c0e7d1..1d34597 100644 --- a/ShoppingAssistantApi.Tests/Tests/UsersTests.cs +++ b/ShoppingAssistantApi.Tests/Tests/UsersTests.cs @@ -1,222 +1,172 @@ using ShoppingAssistantApi.Tests.TestExtentions; -using System.Net.Http.Headers; -using System.Net; -using System.Text; -using Xunit; -using Newtonsoft.Json; using ShoppingAssistantApi.Application.Models.Dtos; +using ShoppingAssistantApi.Application.Models.Identity; +using Newtonsoft.Json.Linq; +using ShoppingAssistantApi.Application.Paging; namespace ShoppingAssistantApi.Tests.Tests; -[Collection("Tests")] -public class UsersTests : IClassFixture> +// TODO: make errors test more descrptive +public class UsersTests : TestsBase { - private readonly HttpClient _httpClient; - public UsersTests(TestingFactory factory) - { - _httpClient = factory.CreateClient(); - factory.InitialaizeData().GetAwaiter().GetResult(); - } + : base(factory) + { } [Fact] public async Task UpdateUserAsync_ValidUserModel_ReturnsUpdateUserModel() { - var tokensModel = await AccessExtention.CreateGuest(Guid.NewGuid().ToString(), _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - - var user = await UserExtention.GetCurrentUser(_httpClient); - - var roles = new object[1]; - - foreach(var role in user.Roles) - { - roles[0] = new - { - id = role.Id, - name = role.Name - }; - } - + await LoginAsync("test@gmail.com", "Yuiop12345"); + var user = await GetCurrentUserAsync(); var mutation = new { - query = "mutation UpdateUser($userDto: UserDtoInput!) { updateUser(userDto: $userDto) { tokens { accessToken, refreshToken }, user { email } }}", + query = @" + mutation UpdateUser($userDto: UserDtoInput!) { + updateUser(userDto: $userDto) { + tokens { accessToken, refreshToken }, + user { email, phone } + } + }", variables = new { userDto = new { id = user.Id, guestId = user.GuestId, - roles = roles, - email = "testing@gmail.com", - password = "Yuiop12345", - refreshTokenExpiryDate = user.RefreshTokenExpiryDate + roles = user.Roles.Select(r => new { id = r.Id, name = r.Name }), + email = user.Email, + phone = "+12345678902", } } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var tokens = (TokensModel?) jsonObject?.data?.updateUser?.tokens?.ToObject(); + var updatedUser = (UserDto?) jsonObject?.data?.updateUser?.user?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessTokenResult = (string)document.data.updateUser.tokens.accessToken; - var refreshTokenResult = (string)document.data.updateUser.tokens.refreshToken; - var userResult = JsonConvert.DeserializeObject(document.data.updateUser.user.ToString()); - - Assert.NotNull(accessTokenResult); - Assert.NotNull(refreshTokenResult); - Assert.NotNull(userResult.Email); + Assert.NotNull(tokens); + Assert.NotNull(tokens.AccessToken); + Assert.NotNull(tokens.RefreshToken); + Assert.NotNull(updatedUser); + Assert.NotNull(updatedUser.Email); + Assert.Equal(user.Email, updatedUser.Email); + Assert.Equal("+12345678902", updatedUser.Phone); } [Fact] public async Task UpdateUserByAdminAsync_ValidUserModel_ReturnsUpdateUserModel() { - var tokensModel = await AccessExtention.CreateGuest(new Guid().ToString(), _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - - var user = await UserExtention.GetCurrentUser(_httpClient); - - var roles = new object[1]; - - foreach (var role in user.Roles) - { - roles[0] = new - { - id = role.Id, - name = role.Name, - }; - } - + await LoginAsync("test@gmail.com", "Yuiop12345"); + var user = await GetCurrentUserAsync(); var mutation = new { - query = "mutation UpdateUserByAdmin($id: String!, $userDto: UserDtoInput!) { updateUserByAdmin(id: $id, userDto: $userDto) { tokens { accessToken, refreshToken }, user { guestId } }}", + query = @" + mutation UpdateUserByAdmin($id: String!, $userDto: UserDtoInput!) { + updateUserByAdmin(id: $id, userDto: $userDto) { + email, + phone + } + }", variables = new { id = user.Id, userDto = new { id = user.Id, - guestId = Guid.NewGuid().ToString(), - roles = roles, - refreshTokenExpiryDate = user.RefreshTokenExpiryDate + guestId = user.GuestId, + roles = user.Roles.Select(r => new { id = r.Id, name = r.Name }), + email = user.Email, + phone = "+12345678903", } } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var updatedUser = (UserDto?) jsonObject?.data?.updateUserByAdmin?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var accessTokenResult = (string)document.data.updateUserByAdmin.tokens.accessToken; - var refreshToken = (string)document.data.updateUserByAdmin.tokens.refreshToken; - var updatedUserGuestId = (Guid)document.data.updateUserByAdmin.user.guestId; - - Assert.NotNull(accessTokenResult); - Assert.NotNull(refreshToken); - Assert.NotEqual(user.GuestId, updatedUserGuestId); + Assert.NotNull(updatedUser); + Assert.NotNull(updatedUser.Email); + Assert.Equal(user.Email, updatedUser.Email); + Assert.Equal("+12345678903", updatedUser.Phone); } [Fact] public async Task GetUserAsync_ValidUserId_ReturnsUser() { - var tokensModel = await AccessExtention.Login("mykhailo.bilodid@nure.ua", "Yuiop12345", _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - - var usersPage = await UserExtention.GetUsers(10, _httpClient); + await LoginAsync("admin@gmail.com", "Yuiop12345"); var query = new { - query = "query User($id: String!) { user(id: $id) { id, email, phone }}", + query = @" + query User($id: String!) { + user(id: $id) { + id, + email + } + }", variables = new { - id = usersPage[0].Id, + id = "652c3b89ae02a3135d6409fc", } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var user = (UserDto?) jsonObject?.data?.user?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - var userResult = JsonConvert.DeserializeObject(document.data.user.ToString()); - Assert.Equal(userResult.Id, usersPage[0].Id); + Assert.NotNull(user); + Assert.Equal("652c3b89ae02a3135d6409fc", user.Id); + Assert.Equal("test@gmail.com", user.Email); } [Fact] public async Task GetUserAsync_InvalidUserId_ReturnsInternalServerError() { - var tokensModel = await AccessExtention.Login("mykhailo.bilodid@nure.ua", "Yuiop12345", _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - + await LoginAsync("admin@gmail.com", "Yuiop12345"); var query = new { - query = "query User($id: String!) { user(id: $id) { id, email, phone }}", + query = "query User($id: String!) { user(id: $id) { id }}", variables = new { - id = "error", + id = "invalid", } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } [Fact] - public async Task GetCurrentUserAsync_ValidCredentials_ReturnsCurrentUser() + public async Task GetCurrentUserAsync_Authorized_ReturnsCurrentUser() { - var tokensModel = await AccessExtention.Login("mykhailo.bilodid@nure.ua", "Yuiop12345", _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - + await LoginAsync("admin@gmail.com", "Yuiop12345"); var query = new { - query = "query CurrentUser { currentUser { id, email, phone }}", - variables = new { } + query = "query CurrentUser { currentUser { id, email, phone }}" }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var user = (UserDto?) jsonObject?.data?.currentUser?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var user = JsonConvert.DeserializeObject(document.data.currentUser.ToString()); - Assert.NotEmpty(user.Id); - Assert.NotEmpty(user.Email); - Assert.NotEmpty(user.Phone); - Assert.Equal(user.Email, "mykhailo.bilodid@nure.ua"); + Assert.NotNull(user); + Assert.Equal("652c3b89ae02a3135d6408fc", user.Id); + Assert.Equal("admin@gmail.com", user.Email); + Assert.Equal("+12345678901", user.Phone); } [Fact] public async Task GetUsersPageAsync_ValidPageNumberAndSize_ReturnsUsersPage() { - var tokensModel = await AccessExtention.Login("mykhailo.bilodid@nure.ua", "Yuiop12345", _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - + await LoginAsync("admin@gmail.com", "Yuiop12345"); var query = new { - query = "query UsersPage($pageNumber: Int!, $pageSize: Int!) { usersPage(pageNumber: $pageNumber, pageSize: $pageSize) { items { id, email, phone }}}", + query = @" + query UsersPage($pageNumber: Int!, $pageSize: Int!) { + usersPage(pageNumber: $pageNumber, pageSize: $pageSize) { + items { id, email, phone } + } + }", variables = new { pageNumber = 1, @@ -224,17 +174,128 @@ public class UsersTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var pagedList = (PagedList?) jsonObject?.data?.usersPage?.ToObject>(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(pagedList); + Assert.NotEmpty(pagedList.Items); + } - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - var items = document.data.usersPage.items; - Assert.NotEmpty(items); + [Fact] + public async Task AddToRoleAsync_ValidRoleName_ReturnsTokensModel() + { + await LoginAsync("admin@gmail.com", "Yuiop12345"); + var mutation = new + { + query = @" + mutation AddToRole($roleName: String!, $userId: String!) { + addToRole(roleName: $roleName, userId: $userId) { + id, email, roles { + name + } + } + }", + variables = new + { + roleName = "Admin", + userId = "652c3b89ae02a3135d6409fc", + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var user = (UserDto?) jsonObject?.data?.addToRole?.ToObject(); + + Assert.NotNull(user); + Assert.Equal("652c3b89ae02a3135d6409fc", user.Id); + Assert.Equal("test@gmail.com", user.Email); + Assert.Contains(user.Roles, r => r.Name == "Admin"); + } + + [Fact] + public async Task AddToRoleAsync_NonExistingRole_ReturnsErrors() + { + await LoginAsync("admin@gmail.com", "Yuiop12345"); + var mutation = new + { + query = @" + mutation AddToRole($roleName: String!, $userId: String!) { + addToRole(roleName: $roleName, userId: $userId) { + id, email, roles { + name + } + } + }", + variables = new + { + roleName = "NonExistingRole", + id = "652c3b89ae02a3135d6409fc", + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; + + Assert.NotNull(errors); + Assert.True(errors.Count > 0); + } + + + [Fact] + public async Task RemoveFromRoleAsync_ValidRoleName_ReturnsTokensModel() + { + await LoginAsync("admin@gmail.com", "Yuiop12345"); + var mutation = new + { + query = @" + mutation RemoveFromRole($roleName: String!, $userId: String!) { + removeFromRole(roleName: $roleName, userId: $userId) { + id, email, roles { + name + } + } + }", + variables = new + { + roleName = "User", + userId = "652c3b89ae02a3135d6409fc", + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var user = (UserDto?) jsonObject?.data?.removeFromRole?.ToObject(); + + Assert.NotNull(user); + Assert.Equal("652c3b89ae02a3135d6409fc", user.Id); + Assert.Equal("test@gmail.com", user.Email); + Assert.DoesNotContain(user.Roles, r => r.Name == "User"); + } + + [Fact] + public async Task RemoveFromRoleAsync_NonExistingRole_ReturnsErrors() + { + await LoginAsync("admin@gmail.com", "Yuiop12345"); + var mutation = new + { + query = @" + mutation RemoveFromRole($roleName: String!, $userId: String!) { + removeFromRole(roleName: $roleName, userId: $userId) { + id, email, roles { + name + } + } + }", + variables = new + { + roleName = "NonExistingRole", + userId = "652c3b89ae02a3135d6409fc", + } + }; + + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; + + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } } diff --git a/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs b/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs index d153a33..0f5b723 100644 --- a/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs +++ b/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs @@ -1,40 +1,39 @@ using ShoppingAssistantApi.Tests.TestExtentions; -using System.Net.Http.Headers; -using System.Net; -using System.Text; -using Xunit; -using Newtonsoft.Json; using ShoppingAssistantApi.Domain.Enums; +using ShoppingAssistantApi.Application.Models.Dtos; +using ShoppingAssistantApi.Application.Paging; +using Newtonsoft.Json.Linq; namespace ShoppingAssistantApi.Tests.Tests; -[Collection("Tests")] -public class WishlistsTests : IClassFixture> +// TODO: make errors test more descrptive +public class WishlistsTests : TestsBase { - private readonly HttpClient _httpClient; + // From DbInitializer + private const string TestingUserId = "652c3b89ae02a3135d6418fc"; - private const string WISHLIST_TESTING_USER_EMAIL = "shopping.assistant.team@gmail.com"; + private const string TestingUserEmail = "wishlists@gmail.com"; - private const string WISHLIST_TESTING_USER_PASSWORD = "Yuiop12345"; + private const string TestingUserPassword = "Yuiop12345"; - private const string TESTING_WISHLIST_ID = "ab79cde6f69abcd3efab65cd"; + private const string TestingWishlistId = "ab79cde6f69abcd3efab65cd"; public WishlistsTests(TestingFactory factory) - { - _httpClient = factory.CreateClient(); - factory.InitialaizeData().GetAwaiter().GetResult(); - } + : base(factory) + { } [Fact] - public async Task StartPersonalWishlistAsync_ValidWishlistModel_ReturnsNewWishlistModels() + public async Task StartPersonalWishlistAsync_ValidWishlist_ReturnsNewWishlist() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - + await LoginAsync(TestingUserEmail, TestingUserPassword); var mutation = new { - query = "mutation startPersonalWishlist($dto: WishlistCreateDtoInput!) { startPersonalWishlist (dto: $dto) { id, name, type, createdById } }", + query = @" + mutation startPersonalWishlist($dto: WishlistCreateDtoInput!) { + startPersonalWishlist (dto: $dto) { + id, name, type, createdById + } + }", variables = new { dto = new @@ -45,36 +44,27 @@ public class WishlistsTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var wishlist = (WishlistDto?) jsonObject?.data?.startPersonalWishlist?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var wishlistId = (string) document.data.startPersonalWishlist.id; - var wishlistCreatedById = (string) document.data.startPersonalWishlist.createdById; - var wishlistType = (string) document.data.startPersonalWishlist.type; - var wishlistName = (string) document.data.startPersonalWishlist.name; - - Assert.Equal(user.Id, wishlistCreatedById); - Assert.Equal(WishlistTypes.Product.ToString(), wishlistType); - Assert.Equal($"{WishlistTypes.Product} Search", wishlistName); + Assert.NotNull(wishlist); + Assert.Equal(TestingUserId, wishlist.CreatedById); + Assert.Equal(WishlistTypes.Product.ToString(), wishlist.Type); + Assert.Equal($"{WishlistTypes.Product} Search", wishlist.Name); } [Fact] public async Task GetPersonalWishlistsPage_ValidPageNumberAndSize_ReturnsPage() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - + await LoginAsync(TestingUserEmail, TestingUserPassword); var query = new { - query = "query personalWishlistsPage($pageNumber: Int!, $pageSize: Int!) { personalWishlistsPage(pageNumber: $pageNumber, pageSize: $pageSize) { items { createdById, id, name, type } } }", + query = @" + query personalWishlistsPage($pageNumber: Int!, $pageSize: Int!) { + personalWishlistsPage(pageNumber: $pageNumber, pageSize: $pageSize) { + items { createdById, id, name, type } + } + }", variables = new { pageNumber = 1, @@ -82,111 +72,84 @@ public class WishlistsTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var pagedList = (PagedList?) jsonObject?.data?.personalWishlistsPage?.ToObject>(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var personalWishlistsPageItems = Enumerable.ToList(document.data.personalWishlistsPage.items); - var personalWishlistCreatedById = (string) personalWishlistsPageItems[0].createdById; - - Assert.NotEmpty(personalWishlistsPageItems); - Assert.Equal(user.Id, personalWishlistCreatedById); + Assert.NotNull(pagedList); + Assert.NotEmpty(pagedList.Items); } [Fact] - public async Task GetPersonalWishlist_ValidWishlistIdOrAuthorizedAccess_ReturnsWishlistDto() + public async Task GetPersonalWishlist_ValidWishlistIdOrAuthorizedAccess_ReturnsWishlist() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - + await LoginAsync(TestingUserEmail, TestingUserPassword); var query = new { - query = "query personalWishlist($wishlistId: String!) { personalWishlist(wishlistId: $wishlistId) { createdById, id, name, type } }", + query = @" + query personalWishlist($wishlistId: String!) { + personalWishlist(wishlistId: $wishlistId) { + createdById, id, name, type + } + }", variables = new { - wishlistId = TESTING_WISHLIST_ID + wishlistId = TestingWishlistId } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var wishlist = (WishlistDto?) jsonObject?.data?.personalWishlist?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var personalWishlistId = (string) document.data.personalWishlist.id; - var personalWishlistName = (string) document.data.personalWishlist.name; - var personalWishlistType = (string) document.data.personalWishlist.type; - var personalWishlistCreatedById = (string) document.data.personalWishlist.createdById; - - Assert.Equal(TESTING_WISHLIST_ID, personalWishlistId); - Assert.Equal("Gaming PC", personalWishlistName); - Assert.Equal(WishlistTypes.Product.ToString(), personalWishlistType); - Assert.Equal(user.Id, personalWishlistCreatedById); + Assert.NotNull(wishlist); + Assert.Equal("Gaming PC", wishlist.Name); + Assert.Equal(WishlistTypes.Product.ToString(), wishlist.Type); + Assert.Equal(TestingUserId, wishlist.CreatedById); } [Fact] public async Task AddMessageToPersonalWishlist_ValidMessageModel_ReturnsNewMessageModel() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - - const string MESSAGE_TEXT = "Second Message"; - + await LoginAsync(TestingUserEmail, TestingUserPassword); + const string MessageText = "Second Message"; var mutation = new { - query = "mutation addMessageToPersonalWishlist($wishlistId: String!, $dto: MessageCreateDtoInput!) { addMessageToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { role, text, createdById } }", + query = @" + mutation addMessageToPersonalWishlist($wishlistId: String!, $dto: MessageCreateDtoInput!) { + addMessageToPersonalWishlist(wishlistId: $wishlistId, dto: $dto) { + role, text, createdById + } + }", variables = new { - wishlistId = TESTING_WISHLIST_ID, + wishlistId = TestingWishlistId, dto = new { - text = MESSAGE_TEXT + text = MessageText } } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var message = (MessageDto?) jsonObject?.data?.addMessageToPersonalWishlist?.ToObject(); - using var response = await _httpClient.PostAsync("graphql", content); - response.EnsureSuccessStatusCode(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - var responseString = await response.Content.ReadAsStringAsync(); - var document = JsonConvert.DeserializeObject(responseString); - - var messageRole = (string) document.data.addMessageToPersonalWishlist.role; - var messageText = (string) document.data.addMessageToPersonalWishlist.text; - var messageCreatedById = (string) document.data.addMessageToPersonalWishlist.createdById; - - Assert.Equal(MessageRoles.User.ToString(), messageRole); - Assert.Equal(MESSAGE_TEXT, messageText); - Assert.Equal(user.Id, messageCreatedById); + Assert.NotNull(message); + Assert.Equal(MessageRoles.User.ToString(), message.Role); + Assert.Equal(MessageText, message.Text); + Assert.Equal(TestingUserId, message.CreatedById); } [Fact] - public async Task StartPersonalWishlistAsync_InvalidWishlistModel_ReturnsInternalServerError() + public async Task StartPersonalWishlistAsync_InvalidWishlist_ReturnsErrors() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - + await LoginAsync(TestingUserEmail, TestingUserPassword); var mutation = new { - query = "mutation startPersonalWishlist($dto: WishlistCreateDtoInput!) { startPersonalWishlist (dto: $dto) { id, name, type, createdById } }", + query = @" + mutation startPersonalWishlist($dto: WishlistCreateDtoInput!) { + startPersonalWishlist (dto: $dto) { + id, name, type, createdById + } + }", variables = new { dto = new @@ -197,85 +160,89 @@ public class WishlistsTests : IClassFixture> } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } [Fact] - public async Task GetPersonalWishlist_InvalidWishlistId_ReturnsInternalServerError() + public async Task GetPersonalWishlist_InvalidWishlistId_ReturnsErrors() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - + await LoginAsync(TestingUserEmail, TestingUserPassword); var query = new { - query = "query personalWishlist($wishlistId: String!) { personalWishlist(wishlistId: $wishlistId) { createdById, id, name, type } }", + query = @" + query personalWishlist($wishlistId: String!) { + personalWishlist(wishlistId: $wishlistId) { + createdById, id, name, type + } + }", variables = new { wishlistId = "1234567890abcdef12345678" // Invalid wishlistId } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } [Fact] - public async Task GetPersonalWishlist_UnAuthorizedAccess_ReturnsInternalServerError() + public async Task GetPersonalWishlist_UnauthorizedAccess_ReturnsErrors() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - + await LoginAsync(TestingUserEmail, TestingUserPassword); var query = new { - query = "query personalWishlist($wishlistId: String!) { personalWishlist(wishlistId: $wishlistId) { createdById, id, name, type } }", + query = @" + query personalWishlist($wishlistId: String!) { + personalWishlist(wishlistId: $wishlistId) { + createdById, id, name, type + } + }", variables = new { wishlistId = "ab6c2c2d9edf39abcd1ef9ab" // Other user's wishlist } }; - var jsonPayload = JsonConvert.SerializeObject(query); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(query); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } [Fact] - public async Task AddMessageToPersonalWishlist_InvalidMessageModel_ReturnsInternalServerError() + public async Task AddMessageToPersonalWishlist_InvalidMessage_ReturnsErrors() { - var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); - var user = await UserExtention.GetCurrentUser(_httpClient); - - const string MESSAGE_TEXT = "Second Message"; - + await LoginAsync(TestingUserEmail, TestingUserPassword); var mutation = new { - query = "mutation addMessageToPersonalWishlist($wishlistId: String!, $dto: MessageCreateDtoInput!) { addMessageToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { role, text, createdById } }", + query = @" + mutation addMessageToPersonalWishlist($wishlistId: String!, $dto: MessageCreateDtoInput!) { + addMessageToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { + role, text, createdById + } + }", variables = new { wishlistId = "8125jad7g12", // Invalid wishlistId dto = new { - text = MESSAGE_TEXT, + text = "random text", } } }; - var jsonPayload = JsonConvert.SerializeObject(mutation); - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var jsonObject = await SendGraphQlRequestAsync(mutation); + var errors = (JArray?) jsonObject?.errors; - using var response = await _httpClient.PostAsync("graphql", content); - Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.NotNull(errors); + Assert.True(errors.Count > 0); } } diff --git a/ShoppingAssistantApi.Tests/Usings.cs b/ShoppingAssistantApi.Tests/Usings.cs new file mode 100644 index 0000000..4f1bf08 --- /dev/null +++ b/ShoppingAssistantApi.Tests/Usings.cs @@ -0,0 +1,4 @@ +global using Xunit; + +// Parallel running was disabled because it causes errors with the database access +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file