Browse Source

Merge branch 'master' of github.com:Squidex/squidex

pull/1235/head
Sebastian Stehle 11 months ago
parent
commit
863fb22cc4
  1. 13
      backend/src/Squidex.Data.EntityFramework/Domain/Apps/Entities/Contents/EFContentRepository.cs
  2. 4
      backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentCollection.cs
  3. 4
      backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentRepository.cs
  4. 4
      backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoShardedContentRepository.cs
  5. 4
      backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Operations/QueryById.cs
  6. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/AddDefaultValues.cs
  7. 19
      backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ExcludeOtherFields.cs
  8. 3
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptingCompleter.cs
  9. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/ValidationExtensions.cs
  10. 9
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs
  11. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs
  12. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs
  13. 46
      backend/tests/Squidex.Data.Tests/Shared/ContentRepositoryTests.cs
  14. 35
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs
  15. 15
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ScriptingCompleterTests.cs
  16. 2
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs
  17. 24
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs
  18. 74
      tools/TestSuite/TestSuite.ApiTests/AssetTests.cs
  19. 9
      tools/TestSuite/TestSuite.ApiTests/BackupTests.cs
  20. 46
      tools/TestSuite/TestSuite.ApiTests/ContentCleanupTests.cs
  21. 34
      tools/TestSuite/TestSuite.ApiTests/ContentCollationTests.cs
  22. 83
      tools/TestSuite/TestSuite.ApiTests/ContentLanguageTests.cs
  23. 44
      tools/TestSuite/TestSuite.ApiTests/ContentQueryTests.cs
  24. 245
      tools/TestSuite/TestSuite.ApiTests/ContentReferencesTests.cs
  25. 99
      tools/TestSuite/TestSuite.ApiTests/ContentScriptingTests.cs
  26. 741
      tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs
  27. 20
      tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs
  28. 45
      tools/TestSuite/TestSuite.ApiTests/RuleRunnerTests.cs

13
backend/src/Squidex.Data.EntityFramework/Domain/Apps/Entities/Contents/EFContentRepository.cs

@ -27,18 +27,18 @@ public sealed partial class EFContentRepository<TContext, TContentContext>(
{
private readonly DynamicTables<TContext, TContentContext> dynamicTables = new DynamicTables<TContext, TContentContext>(dbContextFactory, dbContentContextFactory);
public async Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, SearchScope scope,
public async Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, IReadOnlySet<string>? fields, SearchScope scope,
CancellationToken ct = default)
{
using (Telemetry.Activities.StartActivity("EFContentRepository/FindContentAsync"))
{
return scope == SearchScope.All ?
await FindContentAsync<EFContentCompleteEntity>(app.Id, schema.Id, id, ct) :
await FindContentAsync<EFContentPublishedEntity>(app.Id, schema.Id, id, ct);
await FindContentAsync<EFContentCompleteEntity>(app.Id, schema.Id, id, fields, ct) :
await FindContentAsync<EFContentPublishedEntity>(app.Id, schema.Id, id, fields, ct);
}
}
public async Task<Content?> FindContentAsync<T>(DomainId appId, DomainId schemaId, DomainId id,
public async Task<Content?> FindContentAsync<T>(DomainId appId, DomainId schemaId, DomainId id, IReadOnlySet<string>? fields,
CancellationToken ct = default) where T : EFContentEntity
{
await using var dbContext = await CreateDbContextAsync(ct);
@ -49,6 +49,11 @@ public sealed partial class EFContentRepository<TContext, TContentContext>(
.Where(x => x.IndexedSchemaId == schemaId)
.FirstOrDefaultAsync(ct);
if (fields?.Count > 0)
{
entity?.Data.LimitFields(fields);
}
return entity;
}

4
backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentCollection.cs

@ -213,12 +213,12 @@ public sealed class MongoContentCollection : MongoRepositoryBase<MongoContentEnt
}
}
public async Task<Content?> FindContentAsync(Schema schema, DomainId id,
public async Task<Content?> FindContentAsync(Schema schema, DomainId id, IReadOnlySet<string>? fields,
CancellationToken ct)
{
using (Telemetry.Activities.StartActivity("MongoContentCollection/FindContentAsync"))
{
return await queryBdId.QueryAsync(schema, id, ct);
return await queryBdId.QueryAsync(schema, id, fields, ct);
}
}

4
backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoContentRepository.cs

@ -106,10 +106,10 @@ public partial class MongoContentRepository(
return GetCollection(scope).QueryAsync(app, schema, q, ct);
}
public Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, SearchScope scope,
public Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, IReadOnlySet<string>? fields, SearchScope scope,
CancellationToken ct = default)
{
return GetCollection(scope).FindContentAsync(schema, id, ct);
return GetCollection(scope).FindContentAsync(schema, id, fields, ct);
}
public Task<IReadOnlyList<ContentIdStatus>> QueryIdsAsync(App app, HashSet<DomainId> ids, SearchScope scope,

4
backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/MongoShardedContentRepository.cs

@ -21,10 +21,10 @@ namespace Squidex.Domain.Apps.Entities.Contents;
public sealed class MongoShardedContentRepository(IShardingStrategy sharding, Func<string, MongoContentRepository> factory)
: ShardedSnapshotStore<MongoContentRepository, WriteContent>(sharding, factory, x => x.AppId.Id), IContentRepository, IDeleter
{
public Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, SearchScope scope,
public Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, IReadOnlySet<string>? fields, SearchScope scope,
CancellationToken ct = default)
{
return Shard(app.Id).FindContentAsync(app, schema, id, scope, ct);
return Shard(app.Id).FindContentAsync(app, schema, id, fields, scope, ct);
}
public Task<bool> HasReferrersAsync(App app, DomainId reference, SearchScope scope,

4
backend/src/Squidex.Data.MongoDb/Domain/Apps/Entities/Contents/Operations/QueryById.cs

@ -14,12 +14,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.Operations;
internal sealed class QueryById : OperationBase
{
public async Task<Content?> QueryAsync(Schema schema, DomainId id,
public async Task<Content?> QueryAsync(Schema schema, DomainId id, IReadOnlySet<string>? fields,
CancellationToken ct)
{
var filter = Filter.Eq(x => x.DocumentId, DomainId.Combine(schema.AppId, id));
var contentEntity = await Collection.Find(filter).SelectFields(null).FirstOrDefaultAsync(ct);
var contentEntity = await Collection.Find(filter).SelectFields(fields).FirstOrDefaultAsync(ct);
if (contentEntity == null || contentEntity.IndexedSchemaId != schema.Id)
{
return null;

2
backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/AddDefaultValues.cs

@ -82,7 +82,7 @@ public sealed class AddDefaultValues(PartitionResolver partitionResolver, IClock
private void Enrich(IField field, Dictionary<string, JsonValue> fieldData, string key)
{
if (fieldData.TryGetValue(key, out _) || (field.RawProperties.IsRequired && IgnoreRequiredFields))
if (fieldData.ContainsKey(key) || (field.RawProperties.IsRequired && IgnoreRequiredFields))
{
return;
}

19
backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ExcludeOtherFields.cs

@ -0,0 +1,19 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
namespace Squidex.Domain.Apps.Core.ConvertContent;
public sealed class ExcludeOtherFields(HashSet<string> fieldsToInclude) : IContentFieldConverter
{
public ContentFieldData? ConvertFieldBefore(IRootField field, ContentFieldData source)
{
return fieldsToInclude.Contains(field.Name) ? source : null;
}
}

3
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptingCompleter.cs

@ -233,7 +233,6 @@ public sealed partial class ScriptingCompleter(IEnumerable<IScriptDescriptor> de
AddObject("ctx", FieldDescriptions.FieldRuleContext, () =>
{
Add(JsonType.String, "action",
FieldDescriptions.UserAppRole, ["Create", "Update"]);
});
@ -251,7 +250,7 @@ public sealed partial class ScriptingCompleter(IEnumerable<IScriptDescriptor> de
return Build();
}
private IReadOnlyList<ScriptingValue> Build()
private List<ScriptingValue> Build()
{
return result.Values.OrderBy(x => x.Path).ToList();
}

2
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/ValidationExtensions.cs

@ -150,7 +150,7 @@ public static class ValidationExtensions
operation.Components,
operation.Resolve<IJsonSerializer>())
{
PreviousData = previousData
PreviousData = previousData,
};
var validationContext = new ValidationContext(rootContext).Optimized(optimize).AsPublishing(published);

9
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs

@ -190,12 +190,7 @@ public sealed class ContentQueryService(
{
var schema = await GetSchemaAsync(context, schemaIdOrName, ct);
if (schema == null)
{
throw new DomainObjectNotFoundException(schemaIdOrName);
}
return schema;
return schema ?? throw new DomainObjectNotFoundException(schemaIdOrName);
}
public async Task<Schema?> GetSchemaAsync(Context context, string schemaIdOrName,
@ -277,7 +272,7 @@ public sealed class ContentQueryService(
// Enforce a hard timeout
combined.CancelAfter(options.TimeoutFind);
return await contentRepository.FindContentAsync(context.App, schema, id, context.Scope(), combined.Token);
return await contentRepository.FindContentAsync(context.App, schema, id, context.Fields(), context.Scope(), combined.Token);
}
}

5
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs

@ -154,6 +154,11 @@ public sealed class ConvertData(
}
}
if (fieldNames?.Count > 0)
{
converter.Add(new ExcludeOtherFields(fieldNames));
}
if (!context.IsFrontendClient || context.ResolveSchemaNames())
{
converter.Add(new AddSchemaNames(components));

2
backend/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs

@ -41,7 +41,7 @@ public interface IContentRepository
Task<IReadOnlyList<ContentIdStatus>> QueryIdsAsync(App app, HashSet<DomainId> ids, SearchScope scope,
CancellationToken ct = default);
Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, SearchScope scope,
Task<Content?> FindContentAsync(App app, Schema schema, DomainId id, IReadOnlySet<string>? fields, SearchScope scope,
CancellationToken ct = default);
Task<bool> HasReferrersAsync(App app, DomainId reference, SearchScope scope,

46
backend/tests/Squidex.Data.Tests/Shared/ContentRepositoryTests.cs

@ -163,6 +163,32 @@ public abstract class ContentRepositoryTests : GivenContext
return sut;
}
[Fact]
public async Task Should_find_by_id()
{
var sut = await CreateAndPrepareSutAsync();
var contentId = await sut.StreamAll(app.Id, [schema.Id], default).Select(x => x.Id).FirstOrDefaultAsync();
var content = await sut.FindContentAsync(app, schema, contentId, null, SearchScope.All);
// ID is not predicable, therefore the weak assertion.
Assert.NotNull(content);
}
[Fact]
public async Task Should_find_by_id_with_limited_fields()
{
var sut = await CreateAndPrepareSutAsync();
var contentId = await sut.StreamAll(app.Id, [schema.Id], default).Select(x => x.Id).FirstOrDefaultAsync();
var content = await sut.FindContentAsync(app, schema, contentId, HashSet.Of("field1"), SearchScope.All);
// Only check that the we only go one field.
Assert.NotNull(content);
Assert.Single(content.Data);
Assert.Contains("field1", content.Data);
}
[Fact]
public async Task Should_stream_all_with_schema()
{
@ -170,6 +196,7 @@ public abstract class ContentRepositoryTests : GivenContext
var count = await sut.StreamAll(AppIds[0].Id, [schema.Id], SearchScope.All).CountAsync();
// IDs is not predicable, therefore the weak assertion.
Assert.Equal(NumValues, count);
}
@ -180,6 +207,7 @@ public abstract class ContentRepositoryTests : GivenContext
var count = await sut.StreamAll(AppIds[0].Id, null, SearchScope.All).CountAsync();
// IDs is not predicable, therefore the weak assertion.
Assert.Equal(NumValues * SchemaIds.Length, count);
}
@ -190,6 +218,7 @@ public abstract class ContentRepositoryTests : GivenContext
var count = await sut.StreamAll(AppIds[0].Id, [], SearchScope.All).CountAsync();
// IDs is not predicable, therefore the weak assertion.
Assert.Equal(0, count);
}
@ -288,6 +317,21 @@ public abstract class ContentRepositoryTests : GivenContext
Assert.Equal(NumValues, contents.Count);
}
[Fact]
public async Task Should_query_with_fields()
{
var query = new ClrQuery();
var contents = await QueryAsync(query, fields: HashSet.Of("field1"));
// We have a concrete query, so we expect an actual result.
Assert.All(contents, content =>
{
Assert.Single(content.Data);
Assert.Contains("field1", content.Data);
});
}
[Fact]
public async Task Should_query_with_large_skip()
{
@ -378,6 +422,7 @@ public abstract class ContentRepositoryTests : GivenContext
int skip = 0,
DomainId reference = default,
DomainId referencing = default,
HashSet<string>? fields = null,
bool withTotal = false)
{
clrQuery.Take = top;
@ -396,6 +441,7 @@ public abstract class ContentRepositoryTests : GivenContext
var q =
Q.Empty
.WithFields(fields)
.WithoutTotal(!withTotal)
.WithQuery(clrQuery)
.WithReference(reference)

35
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs

@ -128,6 +128,41 @@ public class FieldConvertersTests
Assert.Equal(expected, actual);
}
[Fact]
public void Should_remove_non_included_fields()
{
var field1 = Fields.Number(1, "number1", Partitioning.Language);
var field2 = Fields.Number(2, "number2", Partitioning.Language);
var schema =
new Schema { Name = "my-schema" }
.AddField(field1)
.AddField(field2);
var source =
new ContentData()
.AddField(field1.Name,
new ContentFieldData()
.AddLocalized("en", 1))
.AddField(field2.Name,
new ContentFieldData()
.AddLocalized("en", JsonValue.Null)
.AddLocalized("de", 1));
var actual =
new ContentConverter(ResolvedComponents.Empty, schema)
.Add(new ExcludeOtherFields(HashSet.Of(field1.Name)))
.Convert(source);
var expected =
new ContentData()
.AddField(field1.Name,
new ContentFieldData()
.AddLocalized("en", 1));
Assert.Equal(expected, actual);
}
[Fact]
public void Should_not_remove_hidden_fields()
{

15
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ScriptingCompleterTests.cs

@ -177,8 +177,7 @@ public class ScriptingCompleterTests
var actual = sut.FieldRule(dataSchema);
AssertCompletion(actual,
new[]
{
[
"ctx",
"ctx.action",
"data",
@ -191,7 +190,7 @@ public class ScriptingCompleterTests
"user.email",
"user.id",
"user.role",
});
]);
}
[Fact]
@ -200,15 +199,14 @@ public class ScriptingCompleterTests
var actual = sut.PreviewUrl(dataSchema);
AssertCompletion(actual,
new[]
{
[
"accessToken",
"data",
"data['my-field']",
"data['my-field'].iv",
"id",
"version",
});
]);
}
[Fact]
@ -356,8 +354,7 @@ public class ScriptingCompleterTests
private static void AssertUsageTrigger(IReadOnlyList<ScriptingValue> actual)
{
AssertCompletion(actual,
new[]
{
[
"event",
"event.appId",
"event.appId.id",
@ -367,7 +364,7 @@ public class ScriptingCompleterTests
"event.name",
"event.timestamp",
"event.version",
});
]);
}
private static void AssertCompletion(IReadOnlyList<ScriptingValue> actual, params string[][] expected)

2
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs

@ -142,7 +142,7 @@ public static class ValidationTestExtensions
components ?? ResolvedComponents.Empty,
TestUtils.DefaultSerializer)
{
PreviousData = previousData
PreviousData = previousData,
};
var context =

24
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs

@ -22,7 +22,6 @@ public class ContentQueryServiceTests : GivenContext
private readonly IContentEnricher contentEnricher = A.Fake<IContentEnricher>();
private readonly IContentRepository contentRepository = A.Fake<IContentRepository>();
private readonly IContentLoader contentVersionLoader = A.Fake<IContentLoader>();
private readonly ContentData contentData = [];
private readonly ContentQueryParser queryParser = A.Fake<ContentQueryParser>();
private readonly ContentQueryService sut;
@ -59,11 +58,9 @@ public class ContentQueryServiceTests : GivenContext
[Fact]
public async Task Should_get_schema_from_guid_string()
{
var input = SchemaId.Id.ToString();
var requestContext = SetupContext();
var actual = await sut.GetSchemaOrThrowAsync(requestContext, input, CancellationToken);
var actual = await sut.GetSchemaOrThrowAsync(requestContext, SchemaId.Id.ToString(), CancellationToken);
Assert.Equal(Schema, actual);
}
@ -71,11 +68,9 @@ public class ContentQueryServiceTests : GivenContext
[Fact]
public async Task Should_get_schema_from_name()
{
var input = SchemaId.Name;
var requestContext = SetupContext();
var actual = await sut.GetSchemaOrThrowAsync(requestContext, input, CancellationToken);
var actual = await sut.GetSchemaOrThrowAsync(requestContext, SchemaId.Name, CancellationToken);
Assert.Equal(Schema, actual);
}
@ -96,21 +91,19 @@ public class ContentQueryServiceTests : GivenContext
var requestContext = SetupContext(allowSchema: false);
var content = CreateContent() as Content;
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, content.Id, A<SearchScope>._, A<CancellationToken>._))
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, content.Id, null, A<SearchScope>._, A<CancellationToken>._))
.Returns(content);
await Assert.ThrowsAsync<DomainForbiddenException>(() => sut.FindAsync(requestContext, SchemaId.Name, content.Id, ct: CancellationToken));
}
[Fact]
public async Task Should_return_null_if_content_by_id_dannot_be_found()
public async Task Should_return_null_if_content_by_id_cannot_be_found()
{
var requestContext = SetupContext();
var content = CreateContent();
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, content.Id, A<SearchScope>._, A<CancellationToken>._))
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, content.Id, A<IReadOnlySet<string>>._, A<SearchScope>._, A<CancellationToken>._))
.Returns<Content?>(null);
var actual = await sut.FindAsync(requestContext, SchemaId.Name, content.Id, ct: CancellationToken);
@ -124,8 +117,7 @@ public class ContentQueryServiceTests : GivenContext
var requestContext = SetupContext();
var content = CreateContent();
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, SchemaId.Id, SearchScope.Published, A<CancellationToken>._))
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, SchemaId.Id, A<IReadOnlySet<string>>._, SearchScope.Published, A<CancellationToken>._))
.Returns(content);
var actual = await sut.FindAsync(requestContext, SchemaId.Name, DomainId.Create("_schemaId_"), ct: CancellationToken);
@ -143,8 +135,7 @@ public class ContentQueryServiceTests : GivenContext
var requestContext = SetupContext(isFrontend, isUnpublished: unpublished);
var content = CreateContent();
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, content.Id, scope, A<CancellationToken>._))
A.CallTo(() => contentRepository.FindContentAsync(App, Schema, content.Id, A<IReadOnlySet<string>>._, scope, A<CancellationToken>._))
.Returns(content);
var actual = await sut.FindAsync(requestContext, SchemaId.Name, content.Id, ct: CancellationToken);
@ -158,7 +149,6 @@ public class ContentQueryServiceTests : GivenContext
var requestContext = SetupContext();
var content = CreateContent();
A.CallTo(() => contentVersionLoader.GetAsync(AppId.Id, content.Id, 13, A<CancellationToken>._))
.Returns(content);

74
tools/TestSuite/TestSuite.ApiTests/AssetTests.cs

@ -589,10 +589,11 @@ public class AssetTests(CreatedAppFixture fixture) : IClassFixture<CreatedAppFix
// STEP 2: Query asset by pixel width.
var assets_1 = await _.Client.Assets.GetAssetsAsync(new AssetQuery
{
Filter = "metadata/pixelWidth eq 600"
});
var assets_1 = await _.Client.Assets.GetAssetsAsync(
new AssetQuery
{
Filter = "metadata/pixelWidth eq 600"
});
Assert.Contains(assets_1.Items, x => x.Id == asset_1.Id);
@ -600,17 +601,20 @@ public class AssetTests(CreatedAppFixture fixture) : IClassFixture<CreatedAppFix
// STEP 3: Add custom metadata.
asset_1.Metadata["custom"] = "foo";
await _.Client.Assets.PutAssetAsync(asset_1.Id, new AnnotateAssetDto
{
Metadata = asset_1.Metadata
});
await _.Client.Assets.PutAssetAsync(
asset_1.Id,
new AnnotateAssetDto
{
Metadata = asset_1.Metadata
});
// STEP 4: Query asset by custom metadata.
var assets_2 = await _.Client.Assets.GetAssetsAsync(new AssetQuery
{
Filter = "metadata/custom eq 'foo'"
});
var assets_2 = await _.Client.Assets.GetAssetsAsync(
new AssetQuery
{
Filter = "metadata/custom eq 'foo'"
});
Assert.Contains(assets_2.Items, x => x.Id == asset_1.Id);
}
@ -623,10 +627,11 @@ public class AssetTests(CreatedAppFixture fixture) : IClassFixture<CreatedAppFix
// STEP 2: Query asset by root folder.
var assets_1 = await _.Client.Assets.GetAssetsAsync(new AssetQuery
{
ParentId = Guid.Empty.ToString()
});
var assets_1 = await _.Client.Assets.GetAssetsAsync(
new AssetQuery
{
ParentId = Guid.Empty.ToString()
});
Assert.Contains(assets_1.Items, x => x.Id == asset_1.Id);
}
@ -648,10 +653,11 @@ public class AssetTests(CreatedAppFixture fixture) : IClassFixture<CreatedAppFix
// STEP 2: Query asset by root folder.
var assets_1 = await _.Client.Assets.GetAssetsAsync(new AssetQuery
{
ParentId = folder.Id
});
var assets_1 = await _.Client.Assets.GetAssetsAsync(
new AssetQuery
{
ParentId = folder.Id
});
Assert.Single(assets_1.Items, x => x.Id == asset_1.Id);
}
@ -727,10 +733,11 @@ public class AssetTests(CreatedAppFixture fixture) : IClassFixture<CreatedAppFix
// STEP 4: Retrieve all deleted items and check if found.
var deleted = await _.Client.Assets.GetAssetsAsync(new AssetQuery
{
Filter = "isDeleted eq true"
});
var deleted = await _.Client.Assets.GetAssetsAsync(
new AssetQuery
{
Filter = "isDeleted eq true"
});
var permanent = strategy is ContentStrategies.Deletion.SinglePermanent or ContentStrategies.Deletion.BulkPermanent;
@ -774,18 +781,19 @@ public class AssetTests(CreatedAppFixture fixture) : IClassFixture<CreatedAppFix
// STEP 3: Query and recreate asset.
var assets = await client.Assets.GetAssetsAsync(new AssetQuery
{
Query = new
var assets = await client.Assets.GetAssetsAsync(
new AssetQuery
{
filter = new
Query = new
{
path = "isDeleted",
op = "eq",
value = true,
filter = new
{
path = "isDeleted",
op = "eq",
value = true,
}
}
}
});
});
Assert.NotEmpty(assets.Items);

9
tools/TestSuite/TestSuite.ApiTests/BackupTests.cs

@ -134,10 +134,11 @@ public class BackupTests(ClientFixture fixture) : IClassFixture<ClientFixture>
var contents = app.Contents<TestEntity, TestEntityData>(schemaName);
await contents.CreateAsync(new TestEntityData
{
Number = 1
});
await contents.CreateAsync(
new TestEntityData
{
Number = 1
});
// Upload a test asset

46
tools/TestSuite/TestSuite.ApiTests/ContentCleanupTests.cs

@ -30,10 +30,11 @@ public class ContentCleanupTests(CreatedAppFixture fixture) : IClassFixture<Crea
// STEP 2: Create a content for this schema.
var content_1 = await contents.CreateAsync(new TestEntityData
{
String = "hello"
});
var content_1 = await contents.CreateAsync(
new TestEntityData
{
String = "hello"
});
Assert.Equal("hello", content_1.Data.String);
@ -43,10 +44,12 @@ public class ContentCleanupTests(CreatedAppFixture fixture) : IClassFixture<Crea
// STEP 4: Make any update.
var content_2 = await contents.ChangeStatusAsync(content_1.Id, new ChangeStatus
{
Status = "Published"
});
var content_2 = await contents.ChangeStatusAsync(
content_1.Id,
new ChangeStatus
{
Status = "Published"
});
// Should not return deleted field.
Assert.Null(content_2.Data.String);
@ -62,17 +65,19 @@ public class ContentCleanupTests(CreatedAppFixture fixture) : IClassFixture<Crea
// STEP 2: Create a referenced content.
var contentA_1 = await contents.CreateAsync(new TestEntityWithReferencesData
{
References = null
});
var contentA_1 = await contents.CreateAsync(
new TestEntityWithReferencesData
{
References = null
});
// STEP 3: Create a content with a reference.
var contentB_1 = await contents.CreateAsync(new TestEntityWithReferencesData
{
References = [contentA_1.Id]
});
var contentB_1 = await contents.CreateAsync(
new TestEntityWithReferencesData
{
References = [contentA_1.Id]
});
// STEP 3: Delete a reference.
@ -80,10 +85,11 @@ public class ContentCleanupTests(CreatedAppFixture fixture) : IClassFixture<Crea
// STEP 4: Make any update.
var contentB_2 = await contents.ChangeStatusAsync(contentB_1.Id, new ChangeStatus
{
Status = "Published"
});
var contentB_2 = await contents.ChangeStatusAsync(contentB_1.Id,
new ChangeStatus
{
Status = "Published"
});
// Should not return deleted field.
Assert.Empty(contentB_2.Data.References!);

34
tools/TestSuite/TestSuite.ApiTests/ContentCollationTests.cs

@ -57,20 +57,26 @@ public class ContentCollationTests(CreatedAppFixture fixture) : IClassFixture<Cr
// STEP 1: Create content.
var contents = _.Client.Contents<SimpleEntity, SimpleEntityData>(schemaName);
await contents.CreateAsync(new SimpleEntityData
{
String = "İstanbul"
}, ContentCreateOptions.AsPublish);
await contents.CreateAsync(new SimpleEntityData
{
String = "Mersin"
}, ContentCreateOptions.AsPublish);
await contents.CreateAsync(new SimpleEntityData
{
String = "Lüleburgaz"
}, ContentCreateOptions.AsPublish);
await contents.CreateAsync(
new SimpleEntityData
{
String = "İstanbul"
},
ContentCreateOptions.AsPublish);
await contents.CreateAsync(
new SimpleEntityData
{
String = "Mersin"
},
ContentCreateOptions.AsPublish);
await contents.CreateAsync(
new SimpleEntityData
{
String = "Lüleburgaz"
},
ContentCreateOptions.AsPublish);
// STEP 2: Get sorted contents.

83
tools/TestSuite/TestSuite.ApiTests/ContentLanguageTests.cs

@ -21,14 +21,17 @@ public class ContentLanguageTests(ContentFixture fixture) : IClassFixture<Conten
public async Task Should_filter_language()
{
// STEP 1: Create content.
var content = await _.Contents.CreateAsync(new TestEntityData
{
Localized = new Dictionary<string, string?>
var content = await _.Contents.CreateAsync(
new TestEntityData
{
["de"] = "Hallo",
["en"] = "Hello"
}
}, ContentCreateOptions.AsPublish, QueryContext.Default.WithLanguages("de"));
Localized = new Dictionary<string, string?>
{
["de"] = "Hallo",
["en"] = "Hello"
}
},
ContentCreateOptions.AsPublish,
QueryContext.Default.WithLanguages("de"));
Assert.False(content.Data.Localized.ContainsKey("en"));
Assert.Equal("Hallo", content.Data.Localized["de"]);
@ -41,15 +44,17 @@ public class ContentLanguageTests(ContentFixture fixture) : IClassFixture<Conten
public async Task Should_flatten_language(string code, string expected)
{
// STEP 1: Create content.
var content = await _.Contents.CreateAsync(new TestEntityData
{
Localized = new Dictionary<string, string?>
var content = await _.Contents.CreateAsync(
new TestEntityData
{
["de"] = "Hallo",
["en"] = "Hello",
["custom"] = "Custom"
}
}, ContentCreateOptions.AsPublish);
Localized = new Dictionary<string, string?>
{
["de"] = "Hallo",
["en"] = "Hello",
["custom"] = "Custom"
}
},
ContentCreateOptions.AsPublish);
// STEP 2: Get content.
@ -64,34 +69,42 @@ public class ContentLanguageTests(ContentFixture fixture) : IClassFixture<Conten
public async Task Should_provide_etag_based_on_headers()
{
// STEP 1: Create content.
var content = await _.Contents.CreateAsync(new TestEntityData
{
Localized = new Dictionary<string, string?>
var content = await _.Contents.CreateAsync(
new TestEntityData
{
["de"] = "Hallo",
["en"] = "Hello"
}
}, ContentCreateOptions.AsPublish);
Localized = new Dictionary<string, string?>
{
["de"] = "Hallo",
["en"] = "Hello"
}
},
ContentCreateOptions.AsPublish);
// STEP 2: Get content.
var (etag1, _) = await GetEtagAsync(content.Id, []);
var (etag2, _) = await GetEtagAsync(content.Id, new Dictionary<string, string>
{
["X-Flatten"] = "1"
});
var (etag2, _) = await GetEtagAsync(
content.Id,
new Dictionary<string, string>
{
["X-Flatten"] = "1"
});
var (etag3, _) = await GetEtagAsync(content.Id, new Dictionary<string, string>
{
["X-Languages"] = "en"
});
var (etag3, _) = await GetEtagAsync(
content.Id,
new Dictionary<string, string>
{
["X-Languages"] = "en"
});
var (etag4, _) = await GetEtagAsync(content.Id, new Dictionary<string, string>
{
["X-Languages"] = "en",
["X-Flatten"] = "1"
});
var (etag4, _) = await GetEtagAsync(
content.Id,
new Dictionary<string, string>
{
["X-Languages"] = "en",
["X-Flatten"] = "1"
});
static void AssertValue(string? value, string? not = null)
{

44
tools/TestSuite/TestSuite.ApiTests/ContentQueryTests.cs

@ -40,7 +40,35 @@ public class ContentQueryTests(ContentQueryFixture fixture) : IClassFixture<Cont
var items_0 = await _.Client.DynamicContents(_.SchemaName).GetAsync(context: context);
Assert.True(items_0.Items.TrueForAll(x => x.Data.Count == 1));
Assert.True(items_0.Items.TrueForAll(x => x.Data.Count == 1 && x.Data.ContainsKey(TestEntityData.StringField)));
}
[Fact]
public async Task Should_find_one()
{
var all = await _.Client.DynamicContents(_.SchemaName).GetAsync();
var content = await _.Client.DynamicContents(_.SchemaName).GetAsync(all.Items[0].Id);
Assert.NotNull(content);
}
[Fact]
public async Task Should_find_one_with_fields()
{
var all = await _.Client.DynamicContents(_.SchemaName).GetAsync();
var context =
QueryContext.Default
.WithFields($"data.{TestEntityData.StringField}");
var content = await _.Client.DynamicContents(_.SchemaName).GetAsync(all.Items[0].Id, context);
Assert.NotNull(content);
Assert.Single(content.Data);
Assert.Contains(TestEntityData.StringField, content.Data);
}
[Fact]
@ -455,13 +483,15 @@ public class ContentQueryTests(ContentQueryFixture fixture) : IClassFixture<Cont
try
{
// STEP 1: Create a content item with a text that caused a bug before.
content = await _.Contents.CreateAsync(new TestEntityData
{
Json = new JObject
content = await _.Contents.CreateAsync(
new TestEntityData
{
["search.field.with.dot"] = 42
}
}, ContentCreateOptions.AsPublish);
Json = new JObject
{
["search.field.with.dot"] = 42
}
},
ContentCreateOptions.AsPublish);
// STEP 2: Get the item and ensure that the text is the same.

245
tools/TestSuite/TestSuite.ApiTests/ContentReferencesTests.cs

@ -21,17 +21,20 @@ public class ContentReferencesTests(ContentReferencesFixture fixture) : IClassFi
public async Task Should_not_deliver_unpublished_references()
{
// STEP 1: Create a referenced content.
var contentA_1 = await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = null
});
var contentA_1 = await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = null
});
// STEP 2: Create a content with a reference.
var contentB_1 = await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = [contentA_1.Id]
}, ContentCreateOptions.AsPublish);
var contentB_1 = await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = [contentA_1.Id]
},
ContentCreateOptions.AsPublish);
// STEP 3: Query new item.
@ -41,10 +44,12 @@ public class ContentReferencesTests(ContentReferencesFixture fixture) : IClassFi
// STEP 4: Publish reference.
await _.Contents.ChangeStatusAsync(contentA_1.Id, new ChangeStatus
{
Status = "Published"
});
await _.Contents.ChangeStatusAsync(
contentA_1.Id,
new ChangeStatus
{
Status = "Published"
});
// STEP 5: Query new item again.
@ -57,17 +62,21 @@ public class ContentReferencesTests(ContentReferencesFixture fixture) : IClassFi
public async Task Should_not_delete_when_referenced()
{
// STEP 1: Create a referenced content.
var contentA_1 = await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = null
}, ContentCreateOptions.AsPublish);
var contentA_1 = await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = null
},
ContentCreateOptions.AsPublish);
// STEP 2: Create a content with a reference.
await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = [contentA_1.Id]
}, ContentCreateOptions.AsPublish);
await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = [contentA_1.Id]
},
ContentCreateOptions.AsPublish);
// STEP 3: Try to delete with referrer check.
@ -87,89 +96,103 @@ public class ContentReferencesTests(ContentReferencesFixture fixture) : IClassFi
public async Task Should_not_unpublish_when_referenced()
{
// STEP 1: Create a published referenced content.
var contentA_1 = await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = null
}, ContentCreateOptions.AsPublish);
var contentA_1 = await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = null
},
ContentCreateOptions.AsPublish);
// STEP 2: Create a content with a reference.
await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = [contentA_1.Id]
}, ContentCreateOptions.AsPublish);
await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = [contentA_1.Id]
},
ContentCreateOptions.AsPublish);
// STEP 3: Try to ThrowsAnyAsync with referrer check.
await Assert.ThrowsAnyAsync<SquidexException>(() =>
{
return _.Contents.ChangeStatusAsync(contentA_1.Id, new ChangeStatus
{
Status = "Draft",
// Ensure that the flag is true.
CheckReferrers = true
});
return _.Contents.ChangeStatusAsync(
contentA_1.Id,
new ChangeStatus
{
Status = "Draft",
// Ensure that the flag is true.
CheckReferrers = true
});
});
// STEP 4: Delete without referrer check.
await _.Contents.ChangeStatusAsync(contentA_1.Id, new ChangeStatus
{
Status = "Draft",
// It is the default anyway, just to make it more explicit.
CheckReferrers = false
});
await _.Contents.ChangeStatusAsync(
contentA_1.Id,
new ChangeStatus
{
Status = "Draft",
// It is the default anyway, just to make it more explicit.
CheckReferrers = false
});
}
[Fact]
public async Task Should_not_delete_with_bulk_when_referenced()
{
// STEP 1: Create a referenced content.
var contentA_1 = await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = null
}, ContentCreateOptions.AsPublish);
var contentA_1 = await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = null
},
ContentCreateOptions.AsPublish);
// STEP 2: Create a content with a reference.
await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = [contentA_1.Id]
}, ContentCreateOptions.AsPublish);
await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = [contentA_1.Id]
},
ContentCreateOptions.AsPublish);
// STEP 3: Try to delete with referrer check.
var result1 = await _.Contents.BulkUpdateAsync(new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.Delete,
Status = "Draft"
},
],
CheckReferrers = true
});
var result1 = await _.Contents.BulkUpdateAsync(
new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.Delete,
Status = "Draft"
},
],
CheckReferrers = true
});
Assert.NotNull(result1[0].Error);
// STEP 4: Delete without referrer check.
var result2 = await _.Contents.BulkUpdateAsync(new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.Delete,
Status = "Draft"
},
],
CheckReferrers = false
});
var result2 = await _.Contents.BulkUpdateAsync(
new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.Delete,
Status = "Draft"
},
],
CheckReferrers = false
});
Assert.Null(result2[0].Error);
}
@ -178,51 +201,57 @@ public class ContentReferencesTests(ContentReferencesFixture fixture) : IClassFi
public async Task Should_not_unpublish_with_bulk_when_referenced()
{
// STEP 1: Create a published referenced content.
var contentA_1 = await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = null
}, ContentCreateOptions.AsPublish);
var contentA_1 = await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = null
},
ContentCreateOptions.AsPublish);
// STEP 2: Create a published content with a reference.
await _.Contents.CreateAsync(new TestEntityWithReferencesData
{
References = [contentA_1.Id]
}, ContentCreateOptions.AsPublish);
await _.Contents.CreateAsync(
new TestEntityWithReferencesData
{
References = [contentA_1.Id]
},
ContentCreateOptions.AsPublish);
// STEP 3: Try to delete with referrer check.
var result1 = await _.Contents.BulkUpdateAsync(new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.ChangeStatus,
Status = "Draft"
},
],
CheckReferrers = true
});
var result1 = await _.Contents.BulkUpdateAsync(
new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.ChangeStatus,
Status = "Draft"
},
],
CheckReferrers = true
});
Assert.NotNull(result1[0].Error);
// STEP 4: Delete without referrer check.
var result2 = await _.Contents.BulkUpdateAsync(new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.ChangeStatus,
Status = "Draft"
},
],
CheckReferrers = false
});
var result2 = await _.Contents.BulkUpdateAsync(
new BulkUpdate
{
Jobs =
[
new BulkUpdateJob
{
Id = contentA_1.Id,
Type = BulkUpdateType.ChangeStatus,
Status = "Draft"
},
],
CheckReferrers = false
});
Assert.Null(result2[0].Error);
}

99
tools/TestSuite/TestSuite.ApiTests/ContentScriptingTests.cs

@ -37,10 +37,11 @@ public class ContentScriptingTests(CreatedAppFixture fixture) : IClassFixture<Cr
// STEP 2: Create content.
var contents = _.Client.Contents<TestEntity, TestEntityData>(schemaName);
var content = await contents.CreateAsync(new TestEntityData
{
Number = 13
});
var content = await contents.CreateAsync(
new TestEntityData
{
Number = 13
});
Assert.Equal(26, content.Data.Number);
}
@ -62,10 +63,12 @@ public class ContentScriptingTests(CreatedAppFixture fixture) : IClassFixture<Cr
// STEP 2: Create content.
var contents = _.Client.Contents<TestEntity, TestEntityData>(schemaName);
var content = await contents.CreateAsync(new TestEntityData
{
Number = 13
}, ContentCreateOptions.AsPublish);
var content = await contents.CreateAsync(
new TestEntityData
{
Number = 13
},
ContentCreateOptions.AsPublish);
Assert.Equal(26, content.Data.Number);
}
@ -89,10 +92,12 @@ public class ContentScriptingTests(CreatedAppFixture fixture) : IClassFixture<Cr
// STEP 2: Create content.
var contents = _.Client.Contents<TestEntity, TestEntityData>(schemaName);
var content = await contents.CreateAsync(new TestEntityData
{
Number = 99
}, ContentCreateOptions.AsPublish);
var content = await contents.CreateAsync(
new TestEntityData
{
Number = 99
},
ContentCreateOptions.AsPublish);
Assert.Equal(19, content.Data.Number);
}
@ -114,26 +119,27 @@ public class ContentScriptingTests(CreatedAppFixture fixture) : IClassFixture<Cr
// STEP 2: Create content with a value that triggers the schema.
var contents = _.Client.Contents<TestEntity, TestEntityData>(schemaName);
var results = await contents.BulkUpdateAsync(new BulkUpdate
{
DoNotScript = false,
DoNotValidate = false,
Jobs =
[
new BulkUpdateJob
{
Type = BulkUpdateType.Upsert,
Data = new
var results = await contents.BulkUpdateAsync(
new BulkUpdate
{
DoNotScript = false,
DoNotValidate = false,
Jobs =
[
new BulkUpdateJob
{
number = new
Type = BulkUpdateType.Upsert,
Data = new
{
iv = 99
number = new
{
iv = 99
}
}
}
},
],
Publish = true
});
},
],
Publish = true
});
Assert.Single(results);
Assert.Null(results[0].Error);
@ -162,26 +168,27 @@ public class ContentScriptingTests(CreatedAppFixture fixture) : IClassFixture<Cr
// STEP 1: Create content with a value that triggers the schema.
var contents = _.Client.Contents<TestEntity, TestEntityData>(schemaName);
var results = await contents.BulkUpdateAsync(new BulkUpdate
{
DoNotScript = true,
DoNotValidate = false,
Jobs =
[
new BulkUpdateJob
{
Type = BulkUpdateType.Upsert,
Data = new
var results = await contents.BulkUpdateAsync(
new BulkUpdate
{
DoNotScript = true,
DoNotValidate = false,
Jobs =
[
new BulkUpdateJob
{
number = new
Type = BulkUpdateType.Upsert,
Data = new
{
iv = 99
number = new
{
iv = 99
}
}
}
},
],
Publish = true
});
},
],
Publish = true
});
Assert.Single(results);
Assert.Null(results[0].Error);

741
tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs

File diff suppressed because it is too large

20
tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs

@ -92,17 +92,19 @@ public sealed class GraphQLTests(GraphQLFixture fixture) : IClassFixture<GraphQL
public async Task Should_query_json()
{
// STEP 1: Create a content with JSON.
var content_0 = await _.Contents.CreateAsync(new TestEntityData
{
Json = JToken.FromObject(new
var content_0 = await _.Contents.CreateAsync(
new TestEntityData
{
value = 1,
obj = new
Json = JToken.FromObject(new
{
value = 2
}
})
}, ContentCreateOptions.AsPublish);
value = 1,
obj = new
{
value = 2
}
})
},
ContentCreateOptions.AsPublish);
// STEP 2: Query this content.

45
tools/TestSuite/TestSuite.ApiTests/RuleRunnerTests.cs

@ -100,23 +100,25 @@ public class RuleRunnerTests(ClientFixture fixture, WebhookCatcherFixture webhoo
// Create a test content.
var referencedContents = app.Contents<TestEntity, TestEntityData>(schemaName);
var referencedContent = await referencedContents.CreateAsync(new TestEntityData
{
String = contentString
});
var referencedContent = await referencedContents.CreateAsync(
new TestEntityData
{
String = contentString
});
var parentSchema = await TestEntityWithReferences.CreateSchemaAsync(app.Schemas, schemaNameRef);
// Create a test content that references the other schema.
var parentContents = app.Contents<TestEntityWithReferences, TestEntityWithReferencesData>(schemaNameRef);
await parentContents.CreateAsync(new TestEntityWithReferencesData
{
References =
[
referencedContent.Id
],
});
await parentContents.CreateAsync(
new TestEntityWithReferencesData
{
References =
[
referencedContent.Id
],
});
// STEP 2: Create rule.
@ -173,13 +175,15 @@ public class RuleRunnerTests(ClientFixture fixture, WebhookCatcherFixture webhoo
var updatedString = Guid.NewGuid().ToString();
var updateEvent = "ReferenceUpdated";
await referencedContents.UpdateAsync(referencedContent.Id, new TestEntityData
{
String = updatedString
});
await referencedContents.UpdateAsync(
referencedContent.Id,
new TestEntityData
{
String = updatedString
});
// Get requests.
// STEP 4: Get requests.
var request = await webhookCatcher.PollAsync(sessionId, x => x.IsPost() && x.HasContent(updatedString) && x.HasContent(updateEvent));
AssertRequest(request);
@ -668,10 +672,11 @@ public class RuleRunnerTests(ClientFixture fixture, WebhookCatcherFixture webhoo
// Create a test content.
var contents = app.Contents<TestEntity, TestEntityData>(schemaName);
await contents.CreateAsync(new TestEntityData
{
String = contentString
});
await contents.CreateAsync(
new TestEntityData
{
String = contentString
});
}
private static async Task<AssetDto> CreateAssetAsync(ISquidexClient app)

Loading…
Cancel
Save