mirror of https://github.com/Squidex/squidex.git
74 changed files with 2179 additions and 515 deletions
@ -1,25 +0,0 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.29123.88 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadTest", "LoadTest.csproj", "{EC732B4F-576E-4853-880D-AA676966D017}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{EC732B4F-576E-4853-880D-AA676966D017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{EC732B4F-576E-4853-880D-AA676966D017}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{EC732B4F-576E-4853-880D-AA676966D017}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{EC732B4F-576E-4853-880D-AA676966D017}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {8ABC073D-D6C6-47F0-AFB6-D42F177D468A} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -1,67 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using LoadTest.Model; |
|||
using LoadTest.Utils; |
|||
using Squidex.ClientLibrary; |
|||
using Xunit; |
|||
|
|||
namespace LoadTest |
|||
{ |
|||
public class ManyItemsTests |
|||
{ |
|||
private readonly SquidexClient<TestEntity, TestEntityData> client; |
|||
|
|||
public ManyItemsTests() |
|||
{ |
|||
client = TestClient.BuildAsync("multiple").Result; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_read_many_async() |
|||
{ |
|||
var contents = await client.GetAsync(); |
|||
|
|||
for (var i = contents.Total; i < 20000; i++) |
|||
{ |
|||
await client.CreateAsync(new TestEntityData |
|||
{ |
|||
String = RandomString.Create(1000) |
|||
}, publish: true); |
|||
} |
|||
|
|||
var found = await client.GetAll2Async(); |
|||
|
|||
Assert.Equal(20000, found.Items.Count); |
|||
} |
|||
} |
|||
|
|||
public static class SquidexClientExtensions |
|||
{ |
|||
public static async Task<SquidexEntities<TEntity, TData>> GetAll2Async<TEntity, TData>(this SquidexClient<TEntity, TData> client, int batchSize = 200) |
|||
where TEntity : SquidexEntityBase<TData> |
|||
where TData : class, new() |
|||
{ |
|||
var query = new ODataQuery { Top = batchSize, Skip = 0 }; |
|||
|
|||
var entities = new SquidexEntities<TEntity, TData>(); |
|||
do |
|||
{ |
|||
var getResult = await client.GetAsync(query); |
|||
|
|||
entities.Total = getResult.Total; |
|||
entities.Items.AddRange(getResult.Items); |
|||
|
|||
query.Skip += getResult.Items.Count; |
|||
} |
|||
while (query.Skip < entities.Total); |
|||
|
|||
return entities; |
|||
} |
|||
} |
|||
} |
|||
@ -1,102 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Squidex.ClientLibrary; |
|||
using Squidex.ClientLibrary.Management; |
|||
|
|||
namespace LoadTest.Model |
|||
{ |
|||
public static class TestClient |
|||
{ |
|||
public const string ServerUrl = "http://localhost:5000"; |
|||
|
|||
public const string ClientId = "root"; |
|||
public const string ClientSecret = "xeLd6jFxqbXJrfmNLlO2j1apagGGGSyZJhFnIuHp4I0="; |
|||
|
|||
public const string TestAppName = "integration-tests"; |
|||
|
|||
public static readonly SquidexClientManager ClientManager = |
|||
new SquidexClientManager( |
|||
ServerUrl, |
|||
TestAppName, |
|||
ClientId, |
|||
ClientSecret) |
|||
{ |
|||
ReadResponseAsString = true |
|||
}; |
|||
|
|||
public static async Task<SquidexClient<TestEntity, TestEntityData>> BuildAsync(string schemaName) |
|||
{ |
|||
await CreateAppIfNotExistsAsync(); |
|||
await CreateSchemaIfNotExistsAsync(schemaName); |
|||
|
|||
return ClientManager.GetClient<TestEntity, TestEntityData>(schemaName); |
|||
} |
|||
|
|||
private static async Task CreateAppIfNotExistsAsync() |
|||
{ |
|||
try |
|||
{ |
|||
var apps = ClientManager.CreateAppsClient(); |
|||
|
|||
await apps.PostAppAsync(new CreateAppDto |
|||
{ |
|||
Name = TestAppName |
|||
}); |
|||
} |
|||
catch (SquidexManagementException ex) |
|||
{ |
|||
if (ex.StatusCode != 400) |
|||
{ |
|||
throw; |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static async Task CreateSchemaIfNotExistsAsync(string schemaName) |
|||
{ |
|||
try |
|||
{ |
|||
var schemas = ClientManager.CreateSchemasClient(); |
|||
|
|||
await schemas.PostSchemaAsync(TestAppName, new CreateSchemaDto |
|||
{ |
|||
Name = schemaName, |
|||
Fields = new List<UpsertSchemaFieldDto> |
|||
{ |
|||
new UpsertSchemaFieldDto |
|||
{ |
|||
Name = "number", |
|||
Properties = new NumberFieldPropertiesDto |
|||
{ |
|||
IsRequired = true |
|||
} |
|||
}, |
|||
new UpsertSchemaFieldDto |
|||
{ |
|||
Name = "string", |
|||
Properties = new StringFieldPropertiesDto |
|||
{ |
|||
IsRequired = false |
|||
} |
|||
} |
|||
}, |
|||
IsPublished = true |
|||
}); |
|||
} |
|||
catch (SquidexManagementException ex) |
|||
{ |
|||
if (ex.StatusCode != 400) |
|||
{ |
|||
throw; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using LoadTest.Model; |
|||
using Squidex.ClientLibrary; |
|||
using Squidex.ClientLibrary.Management; |
|||
|
|||
namespace LoadTest |
|||
{ |
|||
public sealed class ReadingFixture : IDisposable |
|||
{ |
|||
public SquidexClient<TestEntity, TestEntityData> Client { get; private set; } |
|||
|
|||
public IAppsClient AppsClient { get; private set; } |
|||
|
|||
public ReadingFixture() |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
Client = await TestClient.BuildAsync("reading"); |
|||
|
|||
var contents = await Client.GetAllAsync(); |
|||
|
|||
if (contents.Total != 10) |
|||
{ |
|||
foreach (var content in contents.Items) |
|||
{ |
|||
await Client.DeleteAsync(content); |
|||
} |
|||
|
|||
for (var i = 10; i > 0; i--) |
|||
{ |
|||
await Client.CreateAsync(new TestEntityData { Number = i }, true); |
|||
} |
|||
} |
|||
|
|||
AppsClient = TestClient.ClientManager.CreateAppsClient(); |
|||
}).Wait(); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using LoadTest.Model; |
|||
using Squidex.ClientLibrary.Management; |
|||
using Xunit; |
|||
|
|||
namespace LoadTest |
|||
{ |
|||
public sealed class TestUtils |
|||
{ |
|||
[Fact] |
|||
public async Task GenerateAppManyContributorsAsync() |
|||
{ |
|||
var client = TestClient.ClientManager.CreateAppsClient(); |
|||
|
|||
for (var i = 0; i < 200; i++) |
|||
{ |
|||
await client.PostContributorAsync("test", new AssignContributorDto |
|||
{ |
|||
ContributorId = $"hello{i}@squidex.io", Invite = true, Role = "Editor" |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
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 class AppCreationTests : IClassFixture<ClientFixture> |
|||
{ |
|||
public ClientFixture _ { get; } |
|||
|
|||
public AppCreationTests(ClientFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_create_app() |
|||
{ |
|||
var appName = Guid.NewGuid().ToString(); |
|||
|
|||
// STEP 1: Create app
|
|||
var createRequest = new CreateAppDto { Name = appName }; |
|||
|
|||
var app = await _.Apps.PostAppAsync(createRequest); |
|||
|
|||
// Should return create app with correct name.
|
|||
Assert.Equal(appName, app.Name); |
|||
|
|||
|
|||
// STEP 2: Get all apps
|
|||
var apps = await _.Apps.GetAppsAsync(); |
|||
|
|||
// Should provide new app when apps are queried.
|
|||
Assert.Contains(apps, x => x.Name == appName); |
|||
|
|||
|
|||
// STEP 3: Check contributors
|
|||
var contributors = await _.Apps.GetContributorsAsync(appName); |
|||
|
|||
// Should not client itself as a contributor.
|
|||
Assert.Empty(contributors.Items); |
|||
|
|||
|
|||
// STEP 4: Check clients
|
|||
var clients = await _.Apps.GetClientsAsync(appName); |
|||
|
|||
// Should create default client.
|
|||
Assert.Contains(clients.Items, x => x.Id == "default"); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_remove_app() |
|||
{ |
|||
var appName = Guid.NewGuid().ToString(); |
|||
|
|||
// STEP 1: Create app
|
|||
var createRequest = new CreateAppDto { Name = appName }; |
|||
|
|||
await _.Apps.PostAppAsync(createRequest); |
|||
|
|||
|
|||
// STEP 2: Archive app
|
|||
await _.Apps.DeleteAppAsync(appName); |
|||
|
|||
var apps = await _.Apps.GetAppsAsync(); |
|||
|
|||
// Should not provide deleted app when apps are queried.
|
|||
Assert.DoesNotContain(apps, x => x.Name == appName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,367 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
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 AppTests : IClassFixture<CreatedAppFixture> |
|||
{ |
|||
public CreatedAppFixture _ { get; } |
|||
|
|||
public AppTests(CreatedAppFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_get_app() |
|||
{ |
|||
var app = await _.Apps.GetAppAsync(_.AppName); |
|||
|
|||
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 = Guid.NewGuid().ToString(); |
|||
var clientName = "My Client"; |
|||
var clientRole1 = "Editor"; |
|||
var clientRole2 = "Owner"; |
|||
|
|||
// STEP 1: Create client.
|
|||
var createRequest = new CreateClientDto { Id = clientId }; |
|||
|
|||
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.Equal(clientRole1, client_1.Role); |
|||
Assert.Equal(clientId, client_1.Name); |
|||
|
|||
|
|||
// STEP 2: Update client name.
|
|||
var updateNameRequest = new UpdateClientDto { Name = clientName }; |
|||
|
|||
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.Equal(clientName, client_2.Name); |
|||
|
|||
|
|||
// STEP 3: Update client role.
|
|||
var updateRoleRequest = new UpdateClientDto { Role = clientRole2 }; |
|||
|
|||
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.Equal(clientRole2, client_3.Role); |
|||
|
|||
|
|||
// STEP 4: Delete client
|
|||
var clients_4 = await _.Apps.DeleteClientAsync(_.AppName, clientId); |
|||
|
|||
// Should not return deleted client.
|
|||
Assert.DoesNotContain(clients_4.Items, x => x.Id == clientId); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_manage_contributors() |
|||
{ |
|||
var contributorEmail = "hello@squidex.io"; |
|||
var contributorRole1 = "Developer"; |
|||
var contributorRole2 = "Owner"; |
|||
|
|||
// STEP 0: Do not invite contributors when flag is false.
|
|||
var createRequest = new AssignContributorDto { ContributorId = "test@squidex.io" }; |
|||
|
|||
var ex = await Assert.ThrowsAsync<SquidexManagementException>(() => |
|||
{ |
|||
return _.Apps.PostContributorAsync(_.AppName, createRequest); |
|||
}); |
|||
|
|||
Assert.Equal(404, ex.StatusCode); |
|||
|
|||
|
|||
// STEP 1: Assign contributor.
|
|||
var createInviteRequest = new AssignContributorDto { ContributorId = contributorEmail, Invite = true }; |
|||
|
|||
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.Equal(contributorRole1, contributor_1.Role); |
|||
|
|||
|
|||
// STEP 2: Update contributor role.
|
|||
var updateRequest = new AssignContributorDto { ContributorId = contributorEmail, Role = contributorRole2 }; |
|||
|
|||
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.Equal(contributorRole2, contributor_2.Role); |
|||
|
|||
|
|||
// STEP 3: Remove contributor.
|
|||
var contributors3 = await _.Apps.DeleteContributorAsync(_.AppName, contributor_2.ContributorId); |
|||
|
|||
// Should not return deleted contributor.
|
|||
Assert.DoesNotContain(contributors3.Items, x => x.ContributorId == contributor_2.ContributorId); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_manage_roles() |
|||
{ |
|||
var roleName = Guid.NewGuid().ToString(); |
|||
var roleClient = Guid.NewGuid().ToString(); |
|||
var roleContributor1 = "role@squidex.io"; |
|||
var roleContributor2 = "role2@squidex.io"; |
|||
|
|||
// STEP 1: Add role.
|
|||
var createRequest = new AddRoleDto { Name = roleName }; |
|||
|
|||
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.Empty(role_1.Permissions); |
|||
|
|||
|
|||
// STEP 2: Update role.
|
|||
var updateRequest = new UpdateRoleDto { Permissions = new List<string> { "a", "b" } }; |
|||
|
|||
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.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 = roleContributor1, Role = roleName, Invite = true }); |
|||
await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor2, Role = roleName, Invite = true }); |
|||
|
|||
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.Equal(1, role_3.NumClients); |
|||
Assert.Equal(2, role_3.NumContributors); |
|||
|
|||
|
|||
// STEP 4: Try to delete role.
|
|||
var ex = await Assert.ThrowsAsync<SquidexManagementException<ErrorDto>>(() => |
|||
{ |
|||
return _.Apps.DeleteRoleAsync(_.AppName, roleName); |
|||
}); |
|||
|
|||
Assert.Equal(400, ex.StatusCode); |
|||
|
|||
|
|||
// 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 = roleContributor1, Role = fallbackRole }); |
|||
await _.Apps.PostContributorAsync(_.AppName, new AssignContributorDto { ContributorId = roleContributor2, Role = fallbackRole }); |
|||
|
|||
await _.Apps.DeleteRoleAsync(_.AppName, roleName); |
|||
|
|||
var roles_4 = await _.Apps.GetRolesAsync(_.AppName); |
|||
|
|||
// Should not return deleted role.
|
|||
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 not return deleted pattern.
|
|||
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 English 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 German language.
|
|||
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()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
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 class AssetFormatTests : IClassFixture<AssetFixture> |
|||
{ |
|||
public AssetFixture _ { get; } |
|||
|
|||
public AssetFormatTests(AssetFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_image_gif() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleGIFImage_40kbmb.gif", "image/gif"); |
|||
|
|||
// Should parse image metadata.
|
|||
Assert.True(asset.IsImage); |
|||
Assert.Equal(312, asset.PixelHeight); |
|||
Assert.Equal(312, asset.PixelWidth); |
|||
Assert.Equal(312L, asset.Metadata["pixelHeight"]); |
|||
Assert.Equal(312L, asset.Metadata["pixelWidth"]); |
|||
Assert.Equal(AssetType.Image, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_image_gif_without_extension() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleGIFImage_40kbmb.gif", "image/gif", Guid.NewGuid().ToString()); |
|||
|
|||
// Should parse image metadata.
|
|||
Assert.True(asset.IsImage); |
|||
Assert.Equal(312, asset.PixelHeight); |
|||
Assert.Equal(312, asset.PixelWidth); |
|||
Assert.Equal(312L, asset.Metadata["pixelHeight"]); |
|||
Assert.Equal(312L, asset.Metadata["pixelWidth"]); |
|||
Assert.Equal(AssetType.Image, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_image_png() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SamplePNGImage_100kbmb.png", "image/png"); |
|||
|
|||
// Should parse image metadata.
|
|||
Assert.True(asset.IsImage); |
|||
Assert.Equal(170, asset.PixelHeight); |
|||
Assert.Equal(272, asset.PixelWidth); |
|||
Assert.Equal(170L, asset.Metadata["pixelHeight"]); |
|||
Assert.Equal(272L, asset.Metadata["pixelWidth"]); |
|||
Assert.Equal(AssetType.Image, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_image_jpg() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleJPGImage_50kbmb.jpg", "image/jpg"); |
|||
|
|||
// Should parse image metadata.
|
|||
Assert.True(asset.IsImage); |
|||
Assert.Equal(300, asset.PixelHeight); |
|||
Assert.Equal(300, asset.PixelWidth); |
|||
Assert.Equal(300L, asset.Metadata["pixelHeight"]); |
|||
Assert.Equal(300L, asset.Metadata["pixelWidth"]); |
|||
Assert.Equal(96L, asset.Metadata["imageQuality"]); |
|||
Assert.Equal(AssetType.Image, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_audio_mp3() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleAudio_0.4mb.mp3", "audio/mp3"); |
|||
|
|||
// Should parse audio metadata.
|
|||
Assert.False(asset.IsImage); |
|||
Assert.Equal("00:00:28.2708750", asset.Metadata["duration"]); |
|||
Assert.Equal(128L, asset.Metadata["audioBitrate"]); |
|||
Assert.Equal(2L, asset.Metadata["audioChannels"]); |
|||
Assert.Equal(44100L, asset.Metadata["audioSampleRate"]); |
|||
Assert.Equal(AssetType.Audio, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_video_mp4() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleVideo_1280x720_1mb.mp4", "audio/mp4"); |
|||
|
|||
// Should parse video metadata.
|
|||
Assert.False(asset.IsImage); |
|||
Assert.Equal("00:00:05.3120000", asset.Metadata["duration"]); |
|||
Assert.Equal(384L, asset.Metadata["audioBitrate"]); |
|||
Assert.Equal(2L, asset.Metadata["audioChannels"]); |
|||
Assert.Equal(48000L, asset.Metadata["audioSampleRate"]); |
|||
Assert.Equal(1280L, asset.Metadata["videoWidth"]); |
|||
Assert.Equal(720L, asset.Metadata["videoHeight"]); |
|||
Assert.Equal(AssetType.Video, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_video_mkv() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleVideo_1280x720_1mb.flv", "audio/webm"); |
|||
|
|||
// Should not parse yet.
|
|||
Assert.Equal(AssetType.Unknown, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_video_flv() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleVideo_1280x720_1mb.flv", "audio/x-flv"); |
|||
|
|||
// Should not parse yet.
|
|||
Assert.Equal(AssetType.Unknown, asset.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_upload_video_3gp() |
|||
{ |
|||
var asset = await _.UploadFileAsync("Assets/SampleVideo_176x144_1mb.3gp", "audio/3gpp"); |
|||
|
|||
// Should not parse yet.
|
|||
Assert.Equal(AssetType.Unknown, asset.Type); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,157 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Net.Http; |
|||
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 class AssetTests : IClassFixture<AssetFixture> |
|||
{ |
|||
public AssetFixture _ { get; } |
|||
|
|||
public AssetTests(AssetFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_replace_asset() |
|||
{ |
|||
// STEP 1: Create asset
|
|||
var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); |
|||
|
|||
|
|||
// STEP 2: Reupload 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_2); |
|||
|
|||
// Should dowload with correct size.
|
|||
Assert.Equal(stream.Length, downloaded.Length); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_annote_asset() |
|||
{ |
|||
// STEP 1: Create asset
|
|||
var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); |
|||
|
|||
|
|||
// STEP 2: Annotate metadata.
|
|||
var metadataRequest = new AnnotateAssetDto |
|||
{ |
|||
Metadata = new Dictionary<string, object> |
|||
{ |
|||
["pw"] = 100L, |
|||
["ph"] = 20L |
|||
} |
|||
}; |
|||
|
|||
var asset_2 = await _.Assets.PutAssetAsync(_.AppName, asset_1.Id.ToString(), metadataRequest); |
|||
|
|||
// Should provide metadata.
|
|||
Assert.Equal(metadataRequest.Metadata, asset_2.Metadata); |
|||
|
|||
|
|||
// STEP 3: Annotate slug.
|
|||
var slugRequest = new AnnotateAssetDto { Slug = "my-image" }; |
|||
|
|||
var asset_3 = await _.Assets.PutAssetAsync(_.AppName, asset_2.Id.ToString(), slugRequest); |
|||
|
|||
// Should provide updated slug.
|
|||
Assert.Equal(slugRequest.Slug, asset_3.Slug); |
|||
|
|||
|
|||
// STEP 3: Annotate file name.
|
|||
var fileNameRequest = new AnnotateAssetDto { FileName = "My Image" }; |
|||
|
|||
var asset_4 = await _.Assets.PutAssetAsync(_.AppName, asset_3.Id.ToString(), fileNameRequest); |
|||
|
|||
// Should provide updated file name.
|
|||
Assert.Equal(fileNameRequest.FileName, asset_4.FileName); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_protect_asset() |
|||
{ |
|||
var fileName = $"{Guid.NewGuid()}.png"; |
|||
|
|||
// STEP 1: Create asset
|
|||
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_1); |
|||
|
|||
// Should dowload with correct size.
|
|||
Assert.Equal(stream.Length, downloaded.Length); |
|||
} |
|||
|
|||
|
|||
// STEP 4: Protect asset
|
|||
var protectRequest = new AnnotateAssetDto { IsProtected = true }; |
|||
|
|||
var asset_2 = await _.Assets.PutAssetAsync(_.AppName, asset_1.Id.ToString(), protectRequest); |
|||
|
|||
|
|||
// STEP 5: Download asset with authentication.
|
|||
using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open)) |
|||
{ |
|||
var downloaded = new MemoryStream(); |
|||
|
|||
using (var assetStream = await _.Assets.GetAssetContentAsync(asset_2.Id.ToString())) |
|||
{ |
|||
await assetStream.Stream.CopyToAsync(downloaded); |
|||
} |
|||
|
|||
// Should dowload with correct size.
|
|||
Assert.Equal(stream.Length, downloaded.Length); |
|||
} |
|||
|
|||
|
|||
// STEP 5: Download asset without key.
|
|||
using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open)) |
|||
{ |
|||
var ex = await Assert.ThrowsAsync<HttpRequestException>(() => _.DownloadAsync(asset_1)); |
|||
|
|||
// Should return 403 when not authenticated.
|
|||
Assert.Contains("403", ex.Message); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_delete_asset() |
|||
{ |
|||
// STEP 1: Create asset
|
|||
var asset_1 = await _.UploadFileAsync("Assets/logo-squared.png", "image/png"); |
|||
|
|||
|
|||
// STEP 2: Delete asset
|
|||
await _.Assets.DeleteAssetAsync(_.AppName, asset_1.Id.ToString()); |
|||
|
|||
// Should return 404 when asset deleted.
|
|||
var ex = await Assert.ThrowsAsync<SquidexManagementException>(() => _.Assets.GetAssetAsync(_.AppName, asset_1.Id.ToString())); |
|||
|
|||
Assert.Equal(404, ex.StatusCode); |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 102 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,108 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
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 class BackupTests : IClassFixture<ClientFixture> |
|||
{ |
|||
public ClientFixture _ { get; } |
|||
|
|||
public BackupTests(ClientFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_backup_and_restore_app() |
|||
{ |
|||
var timeout = TimeSpan.FromMinutes(2); |
|||
|
|||
var appName = Guid.NewGuid().ToString(); |
|||
var appNameRestore = $"{appName}-restore"; |
|||
|
|||
// STEP 1: Create app
|
|||
var createRequest = new CreateAppDto { Name = appName }; |
|||
|
|||
await _.Apps.PostAppAsync(createRequest); |
|||
|
|||
|
|||
// STEP 2: Create backup
|
|||
await _.Backups.PostBackupAsync(appName); |
|||
|
|||
BackupJobDto backup = null; |
|||
|
|||
try |
|||
{ |
|||
using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2))) |
|||
{ |
|||
while (true) |
|||
{ |
|||
cts.Token.ThrowIfCancellationRequested(); |
|||
|
|||
await Task.Delay(1000); |
|||
|
|||
var backups = await _.Backups.GetBackupsAsync(appName); |
|||
|
|||
if (backups.Items.Count > 0) |
|||
{ |
|||
backup = backups.Items.FirstOrDefault(); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (OperationCanceledException) |
|||
{ |
|||
Assert.True(false, $"Could not retrieve backup within {timeout}."); |
|||
} |
|||
|
|||
|
|||
// STEP 3: Restore backup
|
|||
var uri = new Uri($"{_.ServerUrl}{backup._links["download"].Href}"); |
|||
|
|||
var restoreRequest = new RestoreRequestDto { Url = uri, Name = appNameRestore }; |
|||
|
|||
await _.Backups.PostRestoreJobAsync(restoreRequest); |
|||
|
|||
try |
|||
{ |
|||
using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2))) |
|||
{ |
|||
while (true) |
|||
{ |
|||
cts.Token.ThrowIfCancellationRequested(); |
|||
|
|||
await Task.Delay(1000); |
|||
|
|||
var job = await _.Backups.GetRestoreJobAsync(); |
|||
|
|||
if (job != null && job.Url == uri && job.Status == JobStatus.Completed) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (OperationCanceledException) |
|||
{ |
|||
Assert.True(false, $"Could not retrieve restored app within {timeout}."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,258 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.ClientLibrary; |
|||
using TestSuite.Fixtures; |
|||
using TestSuite.Model; |
|||
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 class ContentQueryTests : IClassFixture<ContentQueryFixture> |
|||
{ |
|||
public ContentQueryFixture _ { get; } |
|||
|
|||
public ContentQueryTests(ContentQueryFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_query_by_ids() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery { OrderBy = "data/number/iv asc" }); |
|||
|
|||
var itemsById = await _.Contents.GetAsync(new HashSet<Guid>(items.Items.Take(3).Select(x => x.EntityId))); |
|||
|
|||
Assert.Equal(3, itemsById.Items.Count); |
|||
Assert.Equal(3, itemsById.Total); |
|||
|
|||
foreach (var item in itemsById.Items) |
|||
{ |
|||
Assert.Equal(_.AppName, item.AppName); |
|||
Assert.Equal(_.SchemaName, item.SchemaName); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_all_with_odata() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery { OrderBy = "data/number/iv asc" }); |
|||
|
|||
AssertItems(items, 10, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_all_with_json() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery |
|||
{ |
|||
JsonQuery = new |
|||
{ |
|||
sort = new[] |
|||
{ |
|||
new |
|||
{ |
|||
path = "data.number.iv", order = "ascending" |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
|
|||
AssertItems(items, 10, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_items_with_skip_with_odata() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery { Skip = 5, OrderBy = "data/number/iv asc" }); |
|||
|
|||
AssertItems(items, 10, new[] { 6, 7, 8, 9, 10 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_items_with_skip_with_json() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery |
|||
{ |
|||
JsonQuery = new |
|||
{ |
|||
sort = new[] |
|||
{ |
|||
new |
|||
{ |
|||
path = "data.number.iv", order = "ascending" |
|||
} |
|||
}, |
|||
skip = 5 |
|||
} |
|||
}); |
|||
|
|||
AssertItems(items, 10, new[] { 6, 7, 8, 9, 10 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_items_with_skip_and_top_with_odata() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery { Skip = 2, Top = 5, OrderBy = "data/number/iv asc" }); |
|||
|
|||
AssertItems(items, 10, new[] { 3, 4, 5, 6, 7 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_items_with_skip_and_top_with_json() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery |
|||
{ |
|||
JsonQuery = new |
|||
{ |
|||
sort = new[] |
|||
{ |
|||
new |
|||
{ |
|||
path = "data.number.iv", order = "ascending" |
|||
} |
|||
}, |
|||
skip = 2, top = 5 |
|||
} |
|||
}); |
|||
|
|||
AssertItems(items, 10, new[] { 3, 4, 5, 6, 7 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_items_with_filter_with_odata() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery { Filter = "data/number/iv gt 3 and data/number/iv lt 7", OrderBy = "data/number/iv asc" }); |
|||
|
|||
AssertItems(items, 3, new[] { 4, 5, 6 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_items_with_filter_with_json() |
|||
{ |
|||
var items = await _.Contents.GetAsync(new ContentQuery |
|||
{ |
|||
JsonQuery = new |
|||
{ |
|||
sort = new[] |
|||
{ |
|||
new |
|||
{ |
|||
path = "data.number.iv", order = "ascending" |
|||
} |
|||
}, |
|||
filter = new |
|||
{ |
|||
and = new[] |
|||
{ |
|||
new |
|||
{ |
|||
path = "data.number.iv", |
|||
op = "gt", |
|||
value = 3 |
|||
}, |
|||
new |
|||
{ |
|||
path = "data.number.iv", |
|||
op = "lt", |
|||
value = 7 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
|
|||
AssertItems(items, 3, new[] { 4, 5, 6 }); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public async Task Should_query_items_with_graphql() |
|||
{ |
|||
var query = new |
|||
{ |
|||
query = @"
|
|||
{ |
|||
queryMyReadsContents(filter: ""data/number/iv gt 3 and data/number/iv lt 7"", orderby: ""data/number/iv asc"") { |
|||
id, |
|||
data { |
|||
number { |
|||
iv |
|||
} |
|||
} |
|||
} |
|||
}"
|
|||
}; |
|||
|
|||
var result = await _.Contents.GraphQlAsync<QueryResult>(query); |
|||
|
|||
var items = result.Items; |
|||
|
|||
Assert.Equal(items.Select(x => x.Data.Number).ToArray(), new[] { 4, 5, 6 }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_query_items_with_graphql_with_dynamic() |
|||
{ |
|||
var query = new |
|||
{ |
|||
query = @"
|
|||
{ |
|||
queryMyReadsContents(filter: ""data/number/iv gt 3 and data/number/iv lt 7"", orderby: ""data/number/iv asc"") { |
|||
id, |
|||
data { |
|||
number { |
|||
iv |
|||
} |
|||
} |
|||
} |
|||
}"
|
|||
}; |
|||
|
|||
var result = await _.Contents.GraphQlAsync<JObject>(query); |
|||
|
|||
var items = result["queryMyReadsContents"]; |
|||
|
|||
Assert.Equal(items.Select(x => x["data"]["number"]["iv"].Value<int>()).ToArray(), new[] { 4, 5, 6 }); |
|||
} |
|||
|
|||
private sealed class QueryResult |
|||
{ |
|||
[JsonProperty("queryMyReadsContents")] |
|||
public QueryItem[] Items { get; set; } |
|||
} |
|||
|
|||
private sealed class QueryItem |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public QueryItemData Data { get; set; } |
|||
} |
|||
|
|||
private sealed class QueryItemData |
|||
{ |
|||
[JsonConverter(typeof(InvariantConverter))] |
|||
public int Number { get; set; } |
|||
} |
|||
|
|||
private void AssertItems(SquidexEntities<TestEntity, TestEntityData> entities, int total, int[] expected) |
|||
{ |
|||
Assert.Equal(total, entities.Total); |
|||
Assert.Equal(expected, entities.Items.Select(x => x.Data.Number).ToArray()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,210 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using Squidex.ClientLibrary; |
|||
using TestSuite.Fixtures; |
|||
using TestSuite.Model; |
|||
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 class ContentUpdateTests : IClassFixture<ContentFixture> |
|||
{ |
|||
public ContentFixture _ { get; } |
|||
|
|||
public ContentUpdateTests(ContentFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_create_strange_text() |
|||
{ |
|||
const string text = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"; |
|||
|
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { String = text }, true); |
|||
|
|||
var updated = await _.Contents.GetAsync(content.Id); |
|||
|
|||
Assert.Equal(text, updated.Data.String); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_return_not_published_item() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 1 }); |
|||
|
|||
await Assert.ThrowsAsync<SquidexException>(() => _.Contents.GetAsync(content.Id)); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_item_published_with_creation() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 1 }, true); |
|||
|
|||
await _.Contents.GetAsync(content.Id); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_item_published_item() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 1 }); |
|||
|
|||
await _.Contents.ChangeStatusAsync(content.Id, Status.Published); |
|||
await _.Contents.GetAsync(content.Id); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_return_archived_item() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 1 }, true); |
|||
|
|||
await _.Contents.ChangeStatusAsync(content.Id, Status.Archived); |
|||
|
|||
await Assert.ThrowsAsync<SquidexException>(() => _.Contents.GetAsync(content.Id)); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_return_unpublished_item() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 1 }); |
|||
|
|||
await _.Contents.ChangeStatusAsync(content.Id, Status.Published); |
|||
await _.Contents.ChangeStatusAsync(content.Id, Status.Draft); |
|||
|
|||
await Assert.ThrowsAsync<SquidexException>(() => _.Contents.GetAsync(content.Id)); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_update_item() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 2 }, true); |
|||
|
|||
await _.Contents.UpdateAsync(content.Id, new TestEntityData { Number = 2 }); |
|||
|
|||
var updated = await _.Contents.GetAsync(content.Id); |
|||
|
|||
Assert.Equal(2, updated.Data.Number); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_patch_item() |
|||
{ |
|||
TestEntity content = null; |
|||
try |
|||
{ |
|||
content = await _.Contents.CreateAsync(new TestEntityData { Number = 1 }, true); |
|||
|
|||
await _.Contents.PatchAsync(content.Id, new TestEntityData { Number = 2 }); |
|||
|
|||
var updated = await _.Contents.GetAsync(content.Id); |
|||
|
|||
Assert.Equal(2, updated.Data.Number); |
|||
} |
|||
finally |
|||
{ |
|||
if (content.Id != null) |
|||
{ |
|||
await _.Contents.DeleteAsync(content.Id); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_delete_item() |
|||
{ |
|||
var content = await _.Contents.CreateAsync(new TestEntityData { Number = 2 }, true); |
|||
|
|||
await _.Contents.DeleteAsync(content.Id); |
|||
|
|||
var updated = await _.Contents.GetAsync(); |
|||
|
|||
Assert.DoesNotContain(updated.Items, x => x.Id == content.Id); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
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 class LanguagesTests : IClassFixture<ClientFixture> |
|||
{ |
|||
public ClientFixture _ { get; } |
|||
|
|||
public LanguagesTests(ClientFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_provide_languages() |
|||
{ |
|||
var languages = await _.Languages.GetLanguagesAsync(); |
|||
|
|||
Assert.True(languages.Count > 100); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
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 class PingTests : IClassFixture<CreatedAppFixture> |
|||
{ |
|||
public CreatedAppFixture _ { get; } |
|||
|
|||
public PingTests(CreatedAppFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_ping_service() |
|||
{ |
|||
await _.Ping.GetPingAsync(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_ping_app() |
|||
{ |
|||
await _.Ping.GetAppPingAsync(_.AppName); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_get_info() |
|||
{ |
|||
var infos = await _.Ping.GetInfoAsync(); |
|||
|
|||
Assert.NotNull(infos); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Xunit; |
|||
|
|||
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] |
|||
@ -0,0 +1,60 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>netcoreapp3.0</TargetFramework> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> |
|||
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" /> |
|||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" /> |
|||
<PackageReference Include="xunit" Version="2.4.1" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> |
|||
<PrivateAssets>all</PrivateAssets> |
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> |
|||
</PackageReference> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<CodeAnalysisRuleSet>..\..\..\Squidex.ruleset</CodeAnalysisRuleSet> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<AdditionalFiles Include="..\..\..\stylecop.json" Link="stylecop.json" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\TestSuite.Shared\TestSuite.Shared.csproj" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Folder Include="Assets\" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Update="Assets\logo-squared.png"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\logo-wide.png"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleAudio_0.4mb.mp3"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleGIFImage_40kbmb.gif"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleJPGImage_50kbmb.jpg"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SamplePNGImage_100kbmb.png"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleVideo_1280x720_1mb.flv"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleVideo_1280x720_1mb.mkv"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleVideo_1280x720_1mb.mp4"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Assets\SampleVideo_176x144_1mb.3gp"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,71 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
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.LoadTests |
|||
{ |
|||
public class ReadingBenchmarks : IClassFixture<CreatedAppFixture> |
|||
{ |
|||
public CreatedAppFixture _ { get; } |
|||
|
|||
public ReadingBenchmarks(CreatedAppFixture fixture) |
|||
{ |
|||
_ = fixture; |
|||
} |
|||
|
|||
public static IEnumerable<object[]> Loads() |
|||
{ |
|||
int[] users = |
|||
{ |
|||
1, |
|||
5, |
|||
10, |
|||
20, |
|||
50, |
|||
100 |
|||
}; |
|||
|
|||
int[] loads = |
|||
{ |
|||
1, |
|||
5, |
|||
10, |
|||
20, |
|||
50, |
|||
100, |
|||
1000 |
|||
}; |
|||
|
|||
foreach (var user in users) |
|||
{ |
|||
foreach (var load in loads) |
|||
{ |
|||
yield return new object[] { user, load }; |
|||
} |
|||
} |
|||
|
|||
yield return new object[] { 1, 20000 }; |
|||
} |
|||
|
|||
[Theory] |
|||
[MemberData(nameof(Loads))] |
|||
public async Task Should_return_clients(int numUsers, int numIterationsPerUser) |
|||
{ |
|||
await Run.Parallel(numUsers, numIterationsPerUser, async () => |
|||
{ |
|||
await _.Apps.GetClientsAsync(_.AppName); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using TestSuite.Fixtures; |
|||
|
|||
namespace TestSuite.LoadTests |
|||
{ |
|||
public sealed class ReadingFixture : ContentFixture |
|||
{ |
|||
public ReadingFixture() |
|||
: base("benchmark_reading") |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.IO; |
|||
using System.Net.Http; |
|||
using System.Threading.Tasks; |
|||
using Squidex.ClientLibrary.Management; |
|||
|
|||
namespace TestSuite.Fixtures |
|||
{ |
|||
public class AssetFixture : CreatedAppFixture |
|||
{ |
|||
public IAssetsClient Assets { get; } |
|||
|
|||
public AssetFixture() |
|||
{ |
|||
Assets = ClientManager.CreateAssetsClient(); |
|||
} |
|||
|
|||
public async Task<MemoryStream> DownloadAsync(AssetDto asset) |
|||
{ |
|||
var temp = new MemoryStream(); |
|||
|
|||
using (var client = new HttpClient()) |
|||
{ |
|||
var url = $"{ServerUrl}{asset._links["content"].Href}"; |
|||
|
|||
var response = await client.GetAsync(url); |
|||
|
|||
response.EnsureSuccessStatusCode(); |
|||
|
|||
using (var stream = await response.Content.ReadAsStreamAsync()) |
|||
{ |
|||
await stream.CopyToAsync(temp); |
|||
} |
|||
} |
|||
|
|||
return temp; |
|||
} |
|||
|
|||
public async Task<AssetDto> UploadFileAsync(string path, AssetDto asset, string fileName = null) |
|||
{ |
|||
var fileInfo = new FileInfo(path); |
|||
|
|||
using (var stream = fileInfo.OpenRead()) |
|||
{ |
|||
var upload = new FileParameter(stream, fileName ?? RandomName(fileInfo), asset.MimeType); |
|||
|
|||
return await Assets.PutAssetContentAsync(AppName, asset.Id.ToString(), upload); |
|||
} |
|||
} |
|||
|
|||
public async Task<AssetDto> UploadFileAsync(string path, string mimeType, string fileName = null) |
|||
{ |
|||
var fileInfo = new FileInfo(path); |
|||
|
|||
using (var stream = fileInfo.OpenRead()) |
|||
{ |
|||
var upload = new FileParameter(stream, fileName ?? RandomName(fileInfo), mimeType); |
|||
|
|||
return await Assets.PostAssetAsync(AppName, upload); |
|||
} |
|||
} |
|||
|
|||
private static string RandomName(FileInfo fileInfo) |
|||
{ |
|||
var fileName = $"{Guid.NewGuid()}{fileInfo.Extension}"; |
|||
|
|||
return fileName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.ClientLibrary.Management; |
|||
|
|||
namespace TestSuite.Fixtures |
|||
{ |
|||
public class ClientFixture : ClientManagerFixture |
|||
{ |
|||
public IAppsClient Apps => ClientManager.CreateAppsClient(); |
|||
|
|||
public IBackupsClient Backups => ClientManager.CreateBackupsClient(); |
|||
|
|||
public ILanguagesClient Languages => ClientManager.CreateLanguagesClient(); |
|||
|
|||
public IPingClient Ping => ClientManager.CreatePingClient(); |
|||
|
|||
public IRulesClient Rules => ClientManager.CreateRulesClient(); |
|||
|
|||
public ISchemasClient Schemas => ClientManager.CreateSchemasClient(); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.ClientLibrary; |
|||
|
|||
namespace TestSuite.Fixtures |
|||
{ |
|||
public class ClientManagerFixture : IDisposable |
|||
{ |
|||
public string ServerUrl { get; } = "http://localhost:5000"; |
|||
|
|||
public string ClientId { get; } = "root"; |
|||
|
|||
public string ClientSecret { get; } = "xeLd6jFxqbXJrfmNLlO2j1apagGGGSyZJhFnIuHp4I0="; |
|||
|
|||
public string AppName { get; } = "integration-tests"; |
|||
|
|||
public SquidexClientManager ClientManager { get; } |
|||
|
|||
public ClientManagerFixture() |
|||
{ |
|||
ClientManager = new SquidexClientManager(ServerUrl, AppName, ClientId, ClientSecret) |
|||
{ |
|||
ReadResponseAsString = true |
|||
}; |
|||
} |
|||
|
|||
public virtual void Dispose() |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Squidex.ClientLibrary; |
|||
using Squidex.ClientLibrary.Management; |
|||
using TestSuite.Model; |
|||
|
|||
namespace TestSuite.Fixtures |
|||
{ |
|||
public class ContentFixture : CreatedAppFixture |
|||
{ |
|||
public SquidexClient<TestEntity, TestEntityData> Contents { get; } |
|||
|
|||
public string SchemaName { get; } |
|||
|
|||
public string FieldNumber { get; } = "number"; |
|||
|
|||
public string FieldString { get; } = "string"; |
|||
|
|||
public ContentFixture() |
|||
: this("my-writes") |
|||
{ |
|||
} |
|||
|
|||
protected ContentFixture(string schemaName) |
|||
{ |
|||
SchemaName = schemaName; |
|||
|
|||
Task.Run(async () => |
|||
{ |
|||
try |
|||
{ |
|||
var schemas = ClientManager.CreateSchemasClient(); |
|||
|
|||
await schemas.PostSchemaAsync(AppName, new CreateSchemaDto |
|||
{ |
|||
Name = SchemaName, |
|||
Fields = new List<UpsertSchemaFieldDto> |
|||
{ |
|||
new UpsertSchemaFieldDto |
|||
{ |
|||
Name = FieldNumber, |
|||
Properties = new NumberFieldPropertiesDto |
|||
{ |
|||
IsRequired = true |
|||
} |
|||
}, |
|||
new UpsertSchemaFieldDto |
|||
{ |
|||
Name = FieldString, |
|||
Properties = new StringFieldPropertiesDto |
|||
{ |
|||
IsRequired = false |
|||
} |
|||
} |
|||
}, |
|||
IsPublished = true |
|||
}); |
|||
} |
|||
catch (SquidexManagementException ex) |
|||
{ |
|||
if (ex.StatusCode != 400) |
|||
{ |
|||
throw; |
|||
} |
|||
} |
|||
}).Wait(); |
|||
|
|||
Contents = ClientManager.GetClient<TestEntity, TestEntityData>(SchemaName); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using Squidex.ClientLibrary; |
|||
using TestSuite.Model; |
|||
|
|||
namespace TestSuite.Fixtures |
|||
{ |
|||
public class ContentQueryFixture : ContentFixture |
|||
{ |
|||
public ContentQueryFixture() |
|||
: this("my-reads") |
|||
{ |
|||
} |
|||
|
|||
protected ContentQueryFixture(string schemaName = "my-schema") |
|||
: base(schemaName) |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
Dispose(); |
|||
|
|||
for (var i = 10; i > 0; i--) |
|||
{ |
|||
await Contents.CreateAsync(new TestEntityData { Number = i }, true); |
|||
} |
|||
}).Wait(); |
|||
} |
|||
|
|||
public override void Dispose() |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
var contents = await Contents.GetAllAsync(); |
|||
|
|||
foreach (var content in contents.Items) |
|||
{ |
|||
await Contents.DeleteAsync(content); |
|||
} |
|||
}).Wait(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using Squidex.ClientLibrary.Management; |
|||
|
|||
namespace TestSuite.Fixtures |
|||
{ |
|||
public class CreatedAppFixture : ClientFixture |
|||
{ |
|||
public CreatedAppFixture() |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
try |
|||
{ |
|||
await Apps.PostAppAsync(new CreateAppDto { Name = AppName }); |
|||
} |
|||
catch (SquidexManagementException ex) |
|||
{ |
|||
if (ex.StatusCode != 400) |
|||
{ |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
await Apps.PostContributorAsync(AppName, new AssignContributorDto { ContributorId = "sebastian@squidex.io", Invite = true, Role = "Owner" }); |
|||
}).Wait(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.0</TargetFramework> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" /> |
|||
<PackageReference Include="Squidex.ClientLibrary" Version="4.1.1" /> |
|||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" /> |
|||
<PackageReference Include="xunit" Version="2.4.1" /> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<CodeAnalysisRuleSet>..\..\..\Squidex.ruleset</CodeAnalysisRuleSet> |
|||
<RootNamespace>TestSuite</RootNamespace> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<AdditionalFiles Include="..\..\..\stylecop.json" Link="stylecop.json" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,37 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.29613.14 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSuite.Shared", "TestSuite.Shared\TestSuite.Shared.csproj", "{37484845-5542-4E52-AB00-C4576B84FE75}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSuite.ApiTests", "TestSuite.ApiTests\TestSuite.ApiTests.csproj", "{E5F048CB-5307-4E4C-8DAB-2F1C0E5CACF3}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSuite.LoadTests", "TestSuite.LoadTests\TestSuite.LoadTests.csproj", "{F37572D9-4880-40F4-B3CB-83F58A40CA48}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{37484845-5542-4E52-AB00-C4576B84FE75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{37484845-5542-4E52-AB00-C4576B84FE75}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{37484845-5542-4E52-AB00-C4576B84FE75}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{37484845-5542-4E52-AB00-C4576B84FE75}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{E5F048CB-5307-4E4C-8DAB-2F1C0E5CACF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{E5F048CB-5307-4E4C-8DAB-2F1C0E5CACF3}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{E5F048CB-5307-4E4C-8DAB-2F1C0E5CACF3}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{E5F048CB-5307-4E4C-8DAB-2F1C0E5CACF3}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F37572D9-4880-40F4-B3CB-83F58A40CA48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F37572D9-4880-40F4-B3CB-83F58A40CA48}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F37572D9-4880-40F4-B3CB-83F58A40CA48}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F37572D9-4880-40F4-B3CB-83F58A40CA48}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {9F1CDBED-7D91-4B46-B4C5-0FE086E29285} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
Loading…
Reference in new issue