diff --git a/backend/src/Squidex.Web/FileExtensions.cs b/backend/src/Squidex.Web/FileExtensions.cs index 3ef88e643..bcd2ad6dc 100644 --- a/backend/src/Squidex.Web/FileExtensions.cs +++ b/backend/src/Squidex.Web/FileExtensions.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Http; using Squidex.Infrastructure.Assets; @@ -14,6 +15,16 @@ namespace Squidex.Web { public static AssetFile ToAssetFile(this IFormFile formFile) { + if (string.IsNullOrWhiteSpace(formFile.ContentType)) + { + throw new ValidationException("File content-type is not defined."); + } + + if (string.IsNullOrWhiteSpace(formFile.FileName)) + { + throw new ValidationException("File name is not defined."); + } + return new AssetFile(formFile.FileName, formFile.ContentType, formFile.Length, formFile.OpenReadStream); } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs index 7bf49768a..e748503d2 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs @@ -174,7 +174,7 @@ namespace Squidex.Areas.Api.Controllers.Apps /// [HttpPost] [Route("apps/{app}/image")] - [ProducesResponseType(typeof(AppDto), 201)] + [ProducesResponseType(typeof(AppDto), 200)] [ApiPermission(Permissions.AppUpdateImage)] [ApiCosts(0)] public async Task UploadImage(string app, IFormFile file) @@ -262,7 +262,7 @@ namespace Squidex.Areas.Api.Controllers.Apps /// [HttpDelete] [Route("apps/{app}/image")] - [ProducesResponseType(typeof(AppDto), 201)] + [ProducesResponseType(typeof(AppDto), 200)] [ApiPermission(Permissions.AppUpdate)] [ApiCosts(0)] public async Task DeleteImage(string app) diff --git a/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs index 62726a9bb..5c9a74e67 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs @@ -36,7 +36,7 @@ namespace Squidex.Areas.Api.Controllers.Languages /// [HttpGet] [Route("languages/")] - [ProducesResponseType(typeof(string[]), 200)] + [ProducesResponseType(typeof(LanguageDto[]), 200)] [ApiPermission] public IActionResult GetLanguages() { diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AppLanguagesTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AppLanguagesTests.cs deleted file mode 100644 index bd2b52e8d..000000000 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AppLanguagesTests.cs +++ /dev/null @@ -1,113 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Linq; -using System.Threading.Tasks; -using Squidex.ClientLibrary.Management; -using TestSuite.Fixtures; -using Xunit; - -#pragma warning disable SA1300 // Element should begin with upper-case letter -#pragma warning disable SA1507 // Code should not contain multiple blank lines in a row - -namespace TestSuite.ApiTests -{ - public sealed class AppLanguagesTests : IClassFixture - { - public ClientFixture _ { get; } - - public AppLanguagesTests(ClientFixture fixture) - { - _ = fixture; - } - - [Fact] - public async Task Should_manage_languages() - { - var appName = Guid.NewGuid().ToString(); - - // STEP 1: Add app - var createRequest = new CreateAppDto { Name = appName }; - - await _.Apps.PostAppAsync(createRequest); - - - // STEP 2: Add languages - await _.Apps.PostLanguageAsync(appName, new AddLanguageDto { Language = "de" }); - await _.Apps.PostLanguageAsync(appName, new AddLanguageDto { Language = "it" }); - await _.Apps.PostLanguageAsync(appName, new AddLanguageDto { Language = "fr" }); - - var languages = await _.Apps.GetLanguagesAsync(appName); - - var languageEN = languages.Items.First(x => x.Iso2Code == "en"); - - Assert.Equal(new string[] { "en", "de", "fr", "it" }, languages.Items.Select(x => x.Iso2Code).ToArray()); - Assert.True(languageEN.IsMaster); - - - // STEP 3: Update language1 - var updateRequest1 = new UpdateLanguageDto - { - Fallback = new string[] - { - "fr", - "it" - }, - IsOptional = true - }; - - languages = await _.Apps.PutLanguageAsync(appName, "de", updateRequest1); - - var languageDE = languages.Items.First(x => x.Iso2Code == "de"); - - Assert.Equal(new string[] { "fr", "it" }, languageDE.Fallback.ToArray()); - Assert.True(languageDE.IsOptional); - - - // STEP 4: Update language2 - var updateRequest2 = new UpdateLanguageDto - { - Fallback = new string[] - { - "fr", - "it" - } - }; - - languages = await _.Apps.PutLanguageAsync(appName, "en", updateRequest2); - - languageEN = languages.Items.First(x => x.Iso2Code == "en"); - - Assert.Equal(new string[] { "fr", "it" }, updateRequest2.Fallback.ToArray()); - - - // STEP 5: Change master language - var masterRequest = new UpdateLanguageDto { IsMaster = true }; - - languages = await _.Apps.PutLanguageAsync(appName, "de", masterRequest); - - languageDE = languages.Items.First(x => x.Iso2Code == "de"); - languageEN = languages.Items.First(x => x.Iso2Code == "en"); - - Assert.True(languageDE.IsMaster); - Assert.False(languageDE.IsOptional); - Assert.False(languageEN.IsMaster); - Assert.Empty(languageDE.Fallback); - Assert.Equal(new string[] { "de", "en", "fr", "it" }, languages.Items.Select(x => x.Iso2Code).ToArray()); - - - // STEP 6: RemoveRequest - languages = await _.Apps.DeleteLanguageAsync(appName, "fr"); - - languageEN = languages.Items.First(x => x.Iso2Code == "en"); - - Assert.Equal(new string[] { "it" }, languageEN.Fallback.ToArray()); - Assert.Equal(new string[] { "de", "en", "it" }, languages.Items.Select(x => x.Iso2Code).ToArray()); - } - } -} diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AppTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AppTests.cs index 560a06ee8..f3087e2f5 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AppTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/AppTests.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using Squidex.ClientLibrary.Management; @@ -35,52 +36,112 @@ namespace TestSuite.ApiTests Assert.Equal(_.AppName, app.Name); } + [Fact] + public async Task Should_manage_app_properties() + { + var appLabel = Guid.NewGuid().ToString(); + var appDescription = Guid.NewGuid().ToString(); + + // STEP 1: Update app + var updateRequest = new UpdateAppDto { Label = appLabel, Description = appDescription }; + + var app_1 = await _.Apps.UpdateAppAsync(_.AppName, updateRequest); + + Assert.Equal(appLabel, app_1.Label); + Assert.Equal(appDescription, app_1.Description); + } + + [Fact] + public async Task Should_manage_image() + { + // STEP 1: Upload image. + using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open)) + { + var file = new FileParameter(stream, "logo-squared.png", "image/png"); + + var app_1 = await _.Apps.UploadImageAsync(_.AppName, file); + + // Should contain image link. + Assert.True(app_1._links.ContainsKey("image")); + } + + + // STEP 2: Download image. + using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open)) + { + var temp = new MemoryStream(); + + var downloaded = new MemoryStream(); + + using (var imageStream = await _.Apps.GetImageAsync(_.AppName)) + { + await imageStream.Stream.CopyToAsync(downloaded); + } + + // Should dowload with correct size. + Assert.True(downloaded.Length < stream.Length); + } + + + // STEP 3: Delete Image. + var app_2 = await _.Apps.DeleteImageAsync(_.AppName); + + // Should contain image link. + Assert.False(app_2._links.ContainsKey("image")); + } + [Fact] public async Task Should_manage_clients() { - var clientId = "my-client"; + var clientId = Guid.NewGuid().ToString(); var clientName = "My Client"; - var clientRole = "Owner"; + var clientRole1 = "Editor"; + var clientRole2 = "Owner"; - // STEP 1: Create client + // STEP 1: Create client. var createRequest = new CreateClientDto { Id = clientId }; - var clients1 = await _.Apps.PostClientAsync(_.AppName, createRequest); + var clients_1 = await _.Apps.PostClientAsync(_.AppName, createRequest); + var client_1 = clients_1.Items.Single(x => x.Id == clientId); // Should return client with correct name and id. - Assert.Contains(clients1.Items, x => x.Id == clientId && x.Name == clientId && x.Role == "Editor"); + Assert.Equal(clientRole1, client_1.Role); + Assert.Equal(clientId, client_1.Name); // STEP 2: Update client name. var updateNameRequest = new UpdateClientDto { Name = clientName }; - var clients2 = await _.Apps.PutClientAsync(_.AppName, clientId, updateNameRequest); + var clients_2 = await _.Apps.PutClientAsync(_.AppName, clientId, updateNameRequest); + var client_2 = clients_2.Items.Single(x => x.Id == clientId); // Should update client name. - Assert.Contains(clients2.Items, x => x.Id == clientId && x.Name == clientName && x.Role == "Editor"); + Assert.Equal(clientName, client_2.Name); // STEP 3: Update client role. - var updateRoleRequest = new UpdateClientDto { Role = clientRole }; + var updateRoleRequest = new UpdateClientDto { Role = clientRole2 }; - var clients3 = await _.Apps.PutClientAsync(_.AppName, clientId, updateRoleRequest); + var clients_3 = await _.Apps.PutClientAsync(_.AppName, clientId, updateRoleRequest); + var client_3 = clients_3.Items.Single(x => x.Id == clientId); // Should update client role. - Assert.Contains(clients3.Items, x => x.Id == clientId && x.Name == clientName && x.Role == clientRole); + Assert.Equal(clientRole2, client_3.Role); // STEP 4: Delete client - var clients4 = await _.Apps.DeleteClientAsync(_.AppName, clientId); + var clients_4 = await _.Apps.DeleteClientAsync(_.AppName, clientId); // Should not return deleted client. - Assert.DoesNotContain(clients4.Items, x => x.Id == clientId); + Assert.DoesNotContain(clients_4.Items, x => x.Id == clientId); } [Fact] public async Task Should_manage_contributors() { var contributorEmail = "hello@squidex.io"; - var contributorRole = "Owner"; + var contributorRole1 = "Developer"; + var contributorRole2 = "Owner"; // STEP 0: Do not invite contributors when flag is false. var createRequest = new AssignContributorDto { ContributorId = "test@squidex.io" }; @@ -96,28 +157,28 @@ namespace TestSuite.ApiTests // STEP 1: Assign contributor. var createInviteRequest = new AssignContributorDto { ContributorId = contributorEmail, Invite = true }; - var contributors1 = await _.Apps.PostContributorAsync(_.AppName, createInviteRequest); - - var id = contributors1.Items.FirstOrDefault(x => x.ContributorName == contributorEmail).ContributorId; + var contributors_1 = await _.Apps.PostContributorAsync(_.AppName, createInviteRequest); + var contributor_1 = contributors_1.Items.FirstOrDefault(x => x.ContributorName == contributorEmail); // Should return contributor with correct email. - Assert.Contains(contributors1.Items, x => x.ContributorName == contributorEmail && x.Role == "Developer"); + Assert.Equal(contributorRole1, contributor_1.Role); // STEP 2: Update contributor role. - var updateRequest = new AssignContributorDto { ContributorId = contributorEmail, Role = contributorRole }; + var updateRequest = new AssignContributorDto { ContributorId = contributorEmail, Role = contributorRole2 }; - var contributors2 = await _.Apps.PostContributorAsync(_.AppName, updateRequest); + var contributors_2 = await _.Apps.PostContributorAsync(_.AppName, updateRequest); + var contributor_2 = contributors_2.Items.FirstOrDefault(x => x.ContributorId == contributor_1.ContributorId); // Should return contributor with correct role. - Assert.Contains(contributors2.Items, x => x.ContributorId == id && x.Role == contributorRole); + Assert.Equal(contributorRole2, contributor_2.Role); // STEP 3: Remove contributor. - var contributors3 = await _.Apps.DeleteContributorAsync(_.AppName, id); + var contributors3 = await _.Apps.DeleteContributorAsync(_.AppName, contributor_2.ContributorId); // Should not return deleted contributor. - Assert.DoesNotContain(contributors3.Items, x => x.ContributorId == id); + Assert.DoesNotContain(contributors3.Items, x => x.ContributorId == contributor_2.ContributorId); } [Fact] @@ -125,36 +186,43 @@ namespace TestSuite.ApiTests { var roleName = Guid.NewGuid().ToString(); var roleClient = Guid.NewGuid().ToString(); - var roleContributor = "role@squidex.io"; + var roleContributor1 = "role@squidex.io"; + var roleContributor2 = "role2@squidex.io"; // STEP 1: Add role. var createRequest = new AddRoleDto { Name = roleName }; - var roles1 = await _.Apps.PostRoleAsync(_.AppName, createRequest); + var roles_1 = await _.Apps.PostRoleAsync(_.AppName, createRequest); + var role_1 = roles_1.Items.Single(x => x.Name == roleName); // Should return role with correct name. - Assert.Contains(roles1.Items, x => x.Name == roleName && x.Permissions.Count == 0); + Assert.Empty(role_1.Permissions); // STEP 2: Update role. var updateRequest = new UpdateRoleDto { Permissions = new List { "a", "b" } }; - var roles2 = await _.Apps.PutRoleAsync(_.AppName, roleName, updateRequest); + var roles_2 = await _.Apps.PutRoleAsync(_.AppName, roleName, updateRequest); + var role_2 = roles_2.Items.Single(x => x.Name == roleName); // Should return role with correct name. - Assert.Contains(roles2.Items, x => x.Name == roleName && x.Permissions.SequenceEqual(updateRequest.Permissions)); + Assert.Equal(updateRequest.Permissions, role_2.Permissions); // STEP 3: Assign client and contributor. await _.Apps.PostClientAsync(_.AppName, new CreateClientDto { Id = roleClient }); + await _.Apps.PutClientAsync(_.AppName, roleClient, new UpdateClientDto { Role = roleName }); - await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor, Role = roleName, Invite = true }); + await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor1, Role = roleName, Invite = true }); + await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor2, Role = roleName, Invite = true }); - var roles3 = await _.Apps.GetRolesAsync(_.AppName); + var roles_3 = await _.Apps.GetRolesAsync(_.AppName); + var role_3 = roles_3.Items.Single(x => x.Name == roleName); // Should return role with correct number of users and clients. - Assert.Contains(roles3.Items, x => x.Name == roleName && x.NumClients == 1 && x.NumContributors == 1); + Assert.Equal(1, role_3.NumClients); + Assert.Equal(2, role_3.NumContributors); // STEP 4: Try to delete role. @@ -166,18 +234,134 @@ namespace TestSuite.ApiTests Assert.Equal(400, ex.StatusCode); - // Step 5: Remove after client and contributor removed. + // STEP 5: Remove after client and contributor removed. var fallbackRole = "Developer"; await _.Apps.PutClientAsync(_.AppName, roleClient, new UpdateClientDto { Role = fallbackRole }); - await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor, Role = fallbackRole }); + + await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor1, Role = fallbackRole }); + await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor2, Role = fallbackRole }); await _.Apps.DeleteRoleAsync(_.AppName, roleName); - var roles4 = await _.Apps.GetRolesAsync(_.AppName); + var roles_4 = await _.Apps.GetRolesAsync(_.AppName); // Should not return deleted role. - Assert.DoesNotContain(roles4.Items, x => x.Name == roleName); + Assert.DoesNotContain(roles_4.Items, x => x.Name == roleName); + } + + [Fact] + public async Task Should_manage_patterns() + { + var patternName = Guid.NewGuid().ToString(); + var patternRegex1 = Guid.NewGuid().ToString(); + var patternRegex2 = Guid.NewGuid().ToString(); + + // STEP 1: Add pattern. + var createRequest = new UpdatePatternDto { Name = patternName, Pattern = patternRegex1 }; + + var patterns_1 = await _.Apps.PostPatternAsync(_.AppName, createRequest); + var pattern_1 = patterns_1.Items.Single(x => x.Name == patternName); + + // Should return pattern with correct regex. + Assert.Equal(patternRegex1, pattern_1.Pattern); + + + // STEP 2: Update pattern. + var updateRequest = new UpdatePatternDto { Name = patternName, Pattern = patternRegex2 }; + + var patterns_2 = await _.Apps.PutPatternAsync(_.AppName, pattern_1.Id.ToString(), updateRequest); + var pattern_2 = patterns_2.Items.Single(x => x.Name == patternName); + + // Should return pattern with correct regex. + Assert.Equal(patternRegex2, pattern_2.Pattern); + + + // STEP 3: Remove pattern. + var patterns_3 = await _.Apps.DeletePatternAsync(_.AppName, pattern_2.Id.ToString()); + + // Should return role with correct number of users and clients. + Assert.DoesNotContain(patterns_3.Items, x => x.Id == pattern_2.Id); + } + + [Fact] + public async Task Should_manage_languages() + { + var appName = Guid.NewGuid().ToString(); + + // STEP 1: Add app. + var createRequest = new CreateAppDto { Name = appName }; + + await _.Apps.PostAppAsync(createRequest); + + + // STEP 2: Add languages. + await _.Apps.PostLanguageAsync(appName, new AddLanguageDto { Language = "de" }); + await _.Apps.PostLanguageAsync(appName, new AddLanguageDto { Language = "it" }); + await _.Apps.PostLanguageAsync(appName, new AddLanguageDto { Language = "fr" }); + + var languages_1 = await _.Apps.GetLanguagesAsync(appName); + var languageEN_1 = languages_1.Items.First(x => x.Iso2Code == "en"); + + Assert.Equal(new string[] { "en", "de", "fr", "it" }, languages_1.Items.Select(x => x.Iso2Code).ToArray()); + Assert.True(languageEN_1.IsMaster); + + + // STEP 3: Update language. + var updateRequest1 = new UpdateLanguageDto + { + Fallback = new string[] + { + "fr", + "it" + }, + IsOptional = true + }; + + var languages_2 = await _.Apps.PutLanguageAsync(appName, "de", updateRequest1); + var languageDE_2 = languages_2.Items.First(x => x.Iso2Code == "de"); + + Assert.Equal(new string[] { "fr", "it" }, languageDE_2.Fallback.ToArray()); + Assert.True(languageDE_2.IsOptional); + + + // STEP 4: Update language2. + var updateRequest2 = new UpdateLanguageDto + { + Fallback = new string[] + { + "fr", + "it" + } + }; + + var languages_3 = await _.Apps.PutLanguageAsync(appName, "en", updateRequest2); + var languageEN_3 = languages_3.Items.First(x => x.Iso2Code == "en"); + + Assert.Equal(new string[] { "fr", "it" }, languageEN_3.Fallback.ToArray()); + + + // STEP 5: Change master language. + var masterRequest = new UpdateLanguageDto { IsMaster = true }; + + var languages_4 = await _.Apps.PutLanguageAsync(appName, "de", masterRequest); + + var languageDE_4 = languages_4.Items.First(x => x.Iso2Code == "de"); + var languageEN_4 = languages_4.Items.First(x => x.Iso2Code == "en"); + + Assert.True(languageDE_4.IsMaster); + Assert.False(languageDE_4.IsOptional); + Assert.False(languageEN_4.IsMaster); + Assert.Empty(languageDE_4.Fallback); + Assert.Equal(new string[] { "de", "en", "fr", "it" }, languages_4.Items.Select(x => x.Iso2Code).ToArray()); + + + // STEP 6: Remove language. + var languages_5 = await _.Apps.DeleteLanguageAsync(appName, "fr"); + var languageEN_5 = languages_5.Items.First(x => x.Iso2Code == "en"); + + Assert.Equal(new string[] { "it" }, languageEN_5.Fallback.ToArray()); + Assert.Equal(new string[] { "de", "en", "it" }, languages_5.Items.Select(x => x.Iso2Code).ToArray()); } } } diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs index c03c43bec..6a1f9170d 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs @@ -32,15 +32,15 @@ namespace TestSuite.ApiTests public async Task Should_replace_asset() { // STEP 1: Create asset - var asset = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); + var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); // STEP 2: Reupload asset - asset = await _.UploadFileAsync("Assets/logo-wide.png", asset); + var asset_2 = await _.UploadFileAsync("Assets/logo-wide.png", asset_1); using (var stream = new FileStream("Assets/logo-wide.png", FileMode.Open)) { - var downloaded = await _.DownloadAsync(asset); + var downloaded = await _.DownloadAsync(asset_2); // Should dowload with correct size. Assert.Equal(stream.Length, downloaded.Length); @@ -51,7 +51,7 @@ namespace TestSuite.ApiTests public async Task Should_annote_asset() { // STEP 1: Create asset - var asset = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); + var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); // STEP 2: Annotate metadata. @@ -64,28 +64,28 @@ namespace TestSuite.ApiTests } }; - asset = await _.Assets.PutAssetAsync(_.AppName, asset.Id.ToString(), metadataRequest); + var asset_2 = await _.Assets.PutAssetAsync(_.AppName, asset_1.Id.ToString(), metadataRequest); // Should provide metadata. - Assert.Equal(metadataRequest.Metadata, asset.Metadata); + Assert.Equal(metadataRequest.Metadata, asset_2.Metadata); // STEP 3: Annotate slug. var slugRequest = new AnnotateAssetDto { Slug = "my-image" }; - asset = await _.Assets.PutAssetAsync(_.AppName, asset.Id.ToString(), slugRequest); + var asset_3 = await _.Assets.PutAssetAsync(_.AppName, asset_2.Id.ToString(), slugRequest); // Should provide updated slug. - Assert.Equal(slugRequest.Slug, asset.Slug); + Assert.Equal(slugRequest.Slug, asset_3.Slug); // STEP 3: Annotate file name. var fileNameRequest = new AnnotateAssetDto { FileName = "My Image" }; - asset = await _.Assets.PutAssetAsync(_.AppName, asset.Id.ToString(), fileNameRequest); + var asset_4 = await _.Assets.PutAssetAsync(_.AppName, asset_3.Id.ToString(), fileNameRequest); // Should provide updated file name. - Assert.Equal(fileNameRequest.FileName, asset.FileName); + Assert.Equal(fileNameRequest.FileName, asset_4.FileName); } [Fact] @@ -94,13 +94,13 @@ namespace TestSuite.ApiTests var fileName = $"{Guid.NewGuid()}.png"; // STEP 1: Create asset - var asset = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); + var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); // STEP 2: Download asset using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open)) { - var downloaded = await _.DownloadAsync(asset); + var downloaded = await _.DownloadAsync(asset_1); // Should dowload with correct size. Assert.Equal(stream.Length, downloaded.Length); @@ -110,7 +110,7 @@ namespace TestSuite.ApiTests // STEP 4: Protect asset var protectRequest = new AnnotateAssetDto { IsProtected = true }; - asset = await _.Assets.PutAssetAsync(_.AppName, asset.Id.ToString(), protectRequest); + var asset_2 = await _.Assets.PutAssetAsync(_.AppName, asset_1.Id.ToString(), protectRequest); // STEP 5: Download asset with authentication. @@ -118,7 +118,7 @@ namespace TestSuite.ApiTests { var downloaded = new MemoryStream(); - using (var assetStream = await _.Assets.GetAssetContentAsync(asset.Id.ToString())) + using (var assetStream = await _.Assets.GetAssetContentAsync(asset_2.Id.ToString())) { await assetStream.Stream.CopyToAsync(downloaded); } @@ -131,7 +131,7 @@ namespace TestSuite.ApiTests // STEP 5: Download asset without key. using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open)) { - var ex = await Assert.ThrowsAsync(() => _.DownloadAsync(asset)); + var ex = await Assert.ThrowsAsync(() => _.DownloadAsync(asset_1)); // Should return 403 when not authenticated. Assert.Contains("403", ex.Message); @@ -142,14 +142,14 @@ namespace TestSuite.ApiTests public async Task Should_delete_asset() { // STEP 1: Create asset - var asset = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); + var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); // STEP 2: Delete asset - await _.Assets.DeleteAssetAsync(_.AppName, asset.Id.ToString()); + await _.Assets.DeleteAssetAsync(_.AppName, asset_1.Id.ToString()); // Should return 404 when asset deleted. - var ex = await Assert.ThrowsAsync(() => _.Assets.GetAssetAsync(_.AppName, asset.Id.ToString())); + var ex = await Assert.ThrowsAsync(() => _.Assets.GetAssetAsync(_.AppName, asset_1.Id.ToString())); Assert.Equal(404, ex.StatusCode); } diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs index 77e9e991d..8c6da95c4 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs @@ -30,6 +30,8 @@ namespace TestSuite.ApiTests [Fact] public async Task Should_backup_and_restore_app() { + var timeout = TimeSpan.FromMinutes(2); + var appName = Guid.NewGuid().ToString(); var appNameRestore = $"{appName}-restore"; @@ -44,24 +46,31 @@ namespace TestSuite.ApiTests BackupJobDto backup = null; - using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20))) + try { - while (true) + using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2))) { - cts.Token.ThrowIfCancellationRequested(); + while (true) + { + cts.Token.ThrowIfCancellationRequested(); - await Task.Delay(1000); + await Task.Delay(1000); - var backups = await _.Backups.GetBackupsAsync(appName); + var backups = await _.Backups.GetBackupsAsync(appName); - if (backups.Items.Count > 0) - { - backup = backups.Items.FirstOrDefault(); + if (backups.Items.Count > 0) + { + backup = backups.Items.FirstOrDefault(); - break; + break; + } } } } + catch (OperationCanceledException) + { + Assert.True(false, $"Could not retrieve backup within {timeout}."); + } // STEP 3: Restore backup @@ -71,22 +80,29 @@ namespace TestSuite.ApiTests await _.Backups.PostRestoreJobAsync(restoreRequest); - using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60))) + try { - while (true) + using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2))) { - cts.Token.ThrowIfCancellationRequested(); + while (true) + { + cts.Token.ThrowIfCancellationRequested(); - await Task.Delay(1000); + await Task.Delay(1000); - var job = await _.Backups.GetRestoreJobAsync(); + var job = await _.Backups.GetRestoreJobAsync(); - if (job != null && job.Url == uri && job.Status == JobStatus.Completed) - { - break; + if (job != null && job.Url == uri && job.Status == JobStatus.Completed) + { + break; + } } } } + catch (OperationCanceledException) + { + Assert.True(false, $"Could not retrieve restored app within {timeout}."); + } } } }