diff --git a/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj b/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
index 319d0b3e5..674e6bb5a 100644
--- a/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
+++ b/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
@@ -10,26 +10,26 @@
-
+
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
diff --git a/backend/src/Migrations/Migrations.csproj b/backend/src/Migrations/Migrations.csproj
index dd5435bf3..8fc18e7dc 100644
--- a/backend/src/Migrations/Migrations.csproj
+++ b/backend/src/Migrations/Migrations.csproj
@@ -6,7 +6,7 @@
enable
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Squidex.Domain.Apps.Core.Model.csproj b/backend/src/Squidex.Domain.Apps.Core.Model/Squidex.Domain.Apps.Core.Model.csproj
index 560e691de..32743858a 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Model/Squidex.Domain.Apps.Core.Model.csproj
+++ b/backend/src/Squidex.Domain.Apps.Core.Model/Squidex.Domain.Apps.Core.Model.csproj
@@ -12,7 +12,7 @@
True
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringAsyncJintExtension.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringAsyncJintExtension.cs
index d8963d13c..11214ae30 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringAsyncJintExtension.cs
+++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringAsyncJintExtension.cs
@@ -20,12 +20,12 @@ public sealed class StringAsyncJintExtension : IJintExtension, IScriptDescriptor
private delegate void TextGenerateDelegate(string prompt, Action callback);
private delegate void TextTranslateDelegate(string text, string language, Action callback, string sourceLanguage);
private readonly ITranslator translator;
- private readonly IChatBot chatBot;
+ private readonly IChatAgent chatAgent;
- public StringAsyncJintExtension(ITranslator translator, IChatBot chatBot)
+ public StringAsyncJintExtension(ITranslator translator, IChatAgent chatAgent)
{
this.translator = translator;
- this.chatBot = chatBot;
+ this.chatAgent = chatAgent;
}
public void ExtendAsync(ScriptExecutionContext context)
@@ -61,9 +61,17 @@ public sealed class StringAsyncJintExtension : IJintExtension, IScriptDescriptor
return;
}
- var result = await chatBot.AskQuestionAsync(prompt, ct);
+ var conversationId = Guid.NewGuid().ToString();
+ try
+ {
+ var result = await chatAgent.PromptAsync(conversationId, prompt, ct);
- scheduler.Run(callback, JsValue.FromObject(context.Engine, result.Choices.FirstOrDefault()));
+ scheduler.Run(callback, JsValue.FromObject(context.Engine, result.Text));
+ }
+ finally
+ {
+ await chatAgent.StopConversationAsync(conversationId);
+ }
}
catch (Exception ex)
{
diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj b/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
index 712e8cd48..4803fe9d3 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
+++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
@@ -20,15 +20,15 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
index 6afe1e9d2..961367e41 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
+++ b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
@@ -19,11 +19,11 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs
index 11459e171..75cffd502 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs
@@ -75,6 +75,7 @@ public sealed class AssetCommandMiddleware : CachingDomainObjectMiddleware b
.WithResolveSchemaNames()
.WithNoCleanup()
- .WithNoEnrichment()
- .WithNoAssetEnrichment());
+ .WithNoEnrichment());
this.options = options.Value;
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Jobs/DefaultJobService.cs b/backend/src/Squidex.Domain.Apps.Entities/Jobs/DefaultJobService.cs
index 2ea883fb9..5a010904a 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Jobs/DefaultJobService.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Jobs/DefaultJobService.cs
@@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
+using System.Collections.Concurrent;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure;
using Squidex.Infrastructure.States;
@@ -15,6 +16,7 @@ namespace Squidex.Domain.Apps.Entities.Jobs;
public sealed class DefaultJobService : IJobService, IDeleter
{
+ private readonly ConcurrentDictionary wokenUp = [];
private readonly IMessageBus messaging;
private readonly IEnumerable runners;
private readonly IPersistenceFactory persistence;
@@ -42,6 +44,7 @@ public sealed class DefaultJobService : IJobService, IDeleter
throw new InvalidOperationException("Invalid job.");
}
+ // This should never happen, but just in case we remove a task, it is there to get a proper error.
var runner = runners.FirstOrDefault(x => x.Name == job.TaskName) ??
throw new InvalidOperationException("Invalid job.");
@@ -51,12 +54,13 @@ public sealed class DefaultJobService : IJobService, IDeleter
public async Task StartAsync(DomainId ownerId, JobRequest request,
CancellationToken ct = default)
{
+ // This should never happen, but just in case we remove a task, it is there to get a proper error.
var runner = runners.FirstOrDefault(x => x.Name == request.TaskName) ??
throw new DomainException(T.Get("jobs.invalidTaskName"));
- var state = await GetStateAsync(ownerId, ct);
-
- state.EnsureCanStart(runner);
+ // Wakeup the job handler to clear cancelled runs from previous incarnations of the service.
+ await EnsureWakeupAsync(ownerId, ct);
+ await EnsureCanRunAsync(ownerId, runner, ct);
await messaging.PublishAsync(new JobStart(ownerId, request), null, ct);
}
@@ -76,6 +80,9 @@ public sealed class DefaultJobService : IJobService, IDeleter
public async Task> GetJobsAsync(DomainId ownerId,
CancellationToken ct = default)
{
+ // Wakeup the job handler to clear cancelled runs from previous incarnations of the service.
+ await EnsureWakeupAsync(ownerId, default);
+
var state = await GetStateAsync(ownerId, ct);
return state.Jobs;
@@ -90,4 +97,20 @@ public sealed class DefaultJobService : IJobService, IDeleter
return state.Value;
}
+
+ private async Task EnsureCanRunAsync(DomainId ownerId, IJobRunner runner, CancellationToken ct)
+ {
+ var state = await GetStateAsync(ownerId, ct);
+
+ state.EnsureCanStart(runner);
+ }
+
+ private async Task EnsureWakeupAsync(DomainId ownerId,
+ CancellationToken ct)
+ {
+ if (wokenUp.TryAdd(ownerId, true))
+ {
+ await messaging.PublishAsync(new JobWakeup(ownerId), null, ct);
+ }
+ }
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs b/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs
index b4b95d468..eb82ef8e9 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobProcessor.cs
@@ -54,10 +54,24 @@ public sealed class JobProcessor
{
await state.LoadAsync(ct);
- if (state.Value.Jobs.RemoveAll(x => x.Stopped == null) > 0)
+ var pending = state.Value.Jobs.Where(x => x.Stopped == null);
+
+ if (pending.Any())
{
// This should actually never happen, so we log with warning.
- log.LogWarning("Removed unfinished backups for owner {ownerId} after start.", ownerId);
+ log.LogWarning("Removed unfinished jobs for owner {ownerId} after start.", ownerId);
+
+ foreach (var job in pending.ToList())
+ {
+ var runner = runners.FirstOrDefault(x => x.Name == job.TaskName);
+
+ if (runner != null)
+ {
+ await runner.CleanupAsync(job);
+ }
+
+ state.Value.Jobs.Remove(job);
+ }
await state.WriteAsync(ct);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobWorker.cs b/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobWorker.cs
index 246c28004..c552f2dc4 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobWorker.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Jobs/JobWorker.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using Microsoft.Extensions.DependencyInjection;
+using Squidex.Domain.Apps.Core.ValidateContent;
using Squidex.Infrastructure;
using Squidex.Messaging;
@@ -15,7 +16,8 @@ public sealed class JobWorker :
IMessageHandler,
IMessageHandler,
IMessageHandler,
- IMessageHandler
+ IMessageHandler,
+ IMessageHandler
{
private readonly Dictionary> processors = [];
private readonly Func processorFactory;
@@ -62,6 +64,11 @@ public sealed class JobWorker :
await processor.ClearAsync();
}
+ public Task HandleAsync(JobWakeup message, CancellationToken ct)
+ {
+ return GetJobProcessorAsync(message.OwnerId);
+ }
+
private Task GetJobProcessorAsync(DomainId appId)
{
lock (processors)
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Jobs/Messages.cs b/backend/src/Squidex.Domain.Apps.Entities/Jobs/Messages.cs
index 3a62f3bc2..12fa102fe 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Jobs/Messages.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Jobs/Messages.cs
@@ -20,4 +20,6 @@ public sealed record JobDelete(DomainId OwnerId, DomainId JobId) : JobMessage(Ow
public sealed record JobClear(DomainId OwnerId) : JobMessage(OwnerId);
+public sealed record JobWakeup(DomainId OwnerId) : JobMessage(OwnerId);
+
public abstract record JobMessage(DomainId OwnerId);
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj b/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
index 963611fba..15f54fa59 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
+++ b/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
@@ -24,15 +24,15 @@
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
@@ -41,7 +41,7 @@
-
+
diff --git a/backend/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj b/backend/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj
index 1486d859f..d484250e7 100644
--- a/backend/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj
+++ b/backend/src/Squidex.Domain.Apps.Events/Squidex.Domain.Apps.Events.csproj
@@ -14,7 +14,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj b/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
index 60a317c13..dcdfa3328 100644
--- a/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
+++ b/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
@@ -19,12 +19,12 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj b/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
index cebbfd461..8e355d2fc 100644
--- a/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
+++ b/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
@@ -18,13 +18,13 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
+
diff --git a/backend/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs b/backend/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs
index 432abadff..cc9c7d802 100644
--- a/backend/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs
+++ b/backend/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs
@@ -7,14 +7,12 @@
using EventStore.Client;
using Squidex.Infrastructure.Json;
-using Squidex.Infrastructure.Tasks;
namespace Squidex.Infrastructure.EventSourcing;
internal sealed class GetEventStoreSubscription : IEventSubscription
{
private readonly CancellationTokenSource cts = new CancellationTokenSource();
- private StreamSubscription subscription;
public GetEventStoreSubscription(
IEventSubscriber eventSubscriber,
@@ -25,58 +23,44 @@ internal sealed class GetEventStoreSubscription : IEventSubscription
string? prefix,
StreamFilter filter)
{
+ var ct = cts.Token;
+
#pragma warning disable MA0134 // Observe result of async calls
Task.Run(async () =>
{
- var ct = cts.Token;
-
var streamName = await projectionClient.CreateProjectionAsync(filter);
- async Task OnEvent(StreamSubscription subscription, ResolvedEvent @event,
- CancellationToken ct)
+ var start = FromStream.Start;
+ if (!string.IsNullOrWhiteSpace(position))
{
- var storedEvent = Formatter.Read(@event, prefix, serializer);
-
- await eventSubscriber.OnNextAsync(this, storedEvent);
+ start = FromStream.After(position.ToPosition(true));
}
- void OnError(StreamSubscription subscription, SubscriptionDroppedReason reason, Exception? ex)
+ await using var subscription = client.SubscribeToStream(streamName, start, true, cancellationToken: ct);
+ try
{
- if (reason != SubscriptionDroppedReason.Disposed &&
- reason != SubscriptionDroppedReason.SubscriberError)
+ await foreach (var message in subscription.Messages)
{
- ex ??= new InvalidOperationException($"Subscription closed with reason {reason}.");
+ if (message is StreamMessage.Event @event)
+ {
+ var storedEvent = Formatter.Read(@event.ResolvedEvent, prefix, serializer);
- eventSubscriber.OnErrorAsync(this, ex).AsTask().Forget();
+ await eventSubscriber.OnNextAsync(this, storedEvent);
+ }
}
}
-
- if (!string.IsNullOrWhiteSpace(position))
- {
- var from = FromStream.After(position.ToPosition(true));
-
- subscription = await client.SubscribeToStreamAsync(streamName, from,
- OnEvent, true,
- OnError,
- cancellationToken: ct);
- }
- else
+ catch (Exception ex)
{
- var from = FromStream.Start;
+ var inner = new InvalidOperationException($"Subscription closed.", ex);
- subscription = await client.SubscribeToStreamAsync(streamName, from,
- OnEvent, true,
- OnError,
- cancellationToken: ct);
+ await eventSubscriber.OnErrorAsync(this, ex);
}
- }, cts.Token);
+ }, ct);
#pragma warning restore MA0134 // Observe result of async calls
}
public void Dispose()
{
- subscription?.Dispose();
-
cts.Cancel();
}
diff --git a/backend/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj b/backend/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj
index f6081a278..c808539d7 100644
--- a/backend/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj
+++ b/backend/src/Squidex.Infrastructure.GetEventStore/Squidex.Infrastructure.GetEventStore.csproj
@@ -11,11 +11,11 @@
True
-
-
-
-
-
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj b/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
index 62b4188b5..29ac5948d 100644
--- a/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
+++ b/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
@@ -14,12 +14,12 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
diff --git a/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj b/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
index 46843f7dd..3d5701f1f 100644
--- a/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
+++ b/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
@@ -11,25 +11,25 @@
True
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/backend/src/Squidex.Shared/Squidex.Shared.csproj b/backend/src/Squidex.Shared/Squidex.Shared.csproj
index a39f5b184..53a791d99 100644
--- a/backend/src/Squidex.Shared/Squidex.Shared.csproj
+++ b/backend/src/Squidex.Shared/Squidex.Shared.csproj
@@ -10,7 +10,7 @@
True
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/src/Squidex.Web/Squidex.Web.csproj b/backend/src/Squidex.Web/Squidex.Web.csproj
index 414ca50c9..bb7daafc4 100644
--- a/backend/src/Squidex.Web/Squidex.Web.csproj
+++ b/backend/src/Squidex.Web/Squidex.Web.csproj
@@ -13,10 +13,10 @@
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppImageController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppImageController.cs
index 1e67c827b..cce7cb22d 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppImageController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppImageController.cs
@@ -87,8 +87,8 @@ public sealed class AppImageController : ApiController
activity?.SetTag("fileType", mimeType);
- await using var assetOriginal = new TempAssetFile(resizedAsset, mimeType, 0);
- await using var assetResized = new TempAssetFile(resizedAsset, mimeType, 0);
+ await using var assetOriginal = new TempAssetFile(resizedAsset, mimeType);
+ await using var assetResized = new TempAssetFile(resizedAsset, mimeType);
var resizeOptions = new ResizeOptions
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
index 1f785e148..f6854fd8a 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
@@ -211,8 +211,8 @@ public sealed class AssetContentController : ApiController
activity?.SetTag("fileType", asset.MimeType);
activity?.SetTag("fileSize", asset.FileSize);
- await using var assetOriginal = new TempAssetFile(asset.FileName, asset.MimeType, 0);
- await using var assetResized = new TempAssetFile(asset.FileName, asset.MimeType, 0);
+ await using var assetOriginal = new TempAssetFile(asset.FileName, asset.MimeType);
+ await using var assetResized = new TempAssetFile(asset.FileName, asset.MimeType);
using (Telemetry.Activities.StartActivity("Read"))
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
index 8899dd06c..bc6bc23a8 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
@@ -23,13 +23,13 @@ namespace Squidex.Areas.Api.Controllers.Translations;
public sealed class TranslationsController : ApiController
{
private readonly ITranslator translator;
- private readonly IChatBot chatBot;
+ private readonly IChatAgent chatAgent;
- public TranslationsController(ICommandBus commandBus, ITranslator translator, IChatBot chatBot)
+ public TranslationsController(ICommandBus commandBus, ITranslator translator, IChatAgent chatAgent)
: base(commandBus)
{
this.translator = translator;
- this.chatBot = chatBot;
+ this.chatAgent = chatAgent;
}
///
@@ -64,9 +64,17 @@ public sealed class TranslationsController : ApiController
[ApiCosts(10)]
public async Task PostQuestion(string app, [FromBody] AskDto request)
{
- var result = await chatBot.AskQuestionAsync(request.Prompt, HttpContext.RequestAborted);
- var response = result.Choices;
+ var conversationId = Guid.NewGuid().ToString();
+ try
+ {
+ var result = await chatAgent.PromptAsync(conversationId, request.Prompt, HttpContext.RequestAborted);
+ var response = new string[] { result.Text };
- return Ok(response);
+ return Ok(response);
+ }
+ finally
+ {
+ await chatAgent.StopConversationAsync(conversationId, default);
+ }
}
}
diff --git a/backend/src/Squidex/Config/Domain/FontendServices.cs b/backend/src/Squidex/Config/Domain/FontendServices.cs
index 79d7de7a4..02085dd09 100644
--- a/backend/src/Squidex/Config/Domain/FontendServices.cs
+++ b/backend/src/Squidex/Config/Domain/FontendServices.cs
@@ -51,9 +51,9 @@ public static class FontendServices
services.Configure((services, options) =>
{
- var chatBot = services.GetRequiredService();
+ var chatAgent = services.GetRequiredService();
- options.More["canUseChatBot"] = chatBot.IsConfigured;
+ options.More["canUseChatBot"] = chatAgent.IsConfigured;
});
services.Configure((services, options) =>
diff --git a/backend/src/Squidex/Config/Domain/InfrastructureServices.cs b/backend/src/Squidex/Config/Domain/InfrastructureServices.cs
index 5b559795f..d9d33e812 100644
--- a/backend/src/Squidex/Config/Domain/InfrastructureServices.cs
+++ b/backend/src/Squidex/Config/Domain/InfrastructureServices.cs
@@ -135,7 +135,7 @@ public static class InfrastructureServices
services.AddDeepLTranslations(config);
services.AddGoogleCloudTranslations(config);
- services.AddOpenAIChatBot(config);
+ services.AddOpenAIChatAgent(config);
}
public static void AddSquidexLocalization(this IServiceCollection services)
diff --git a/backend/src/Squidex/Squidex.csproj b/backend/src/Squidex/Squidex.csproj
index 0794d4439..eb24428c0 100644
--- a/backend/src/Squidex/Squidex.csproj
+++ b/backend/src/Squidex/Squidex.csproj
@@ -34,47 +34,47 @@
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
+
+
+
+
+
-
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs
index c67cc9714..43b445a08 100644
--- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs
+++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs
@@ -24,7 +24,7 @@ public class JintScriptEngineHelperTests : IClassFixture
{
private readonly IHttpClientFactory httpClientFactory = A.Fake();
private readonly ITranslator translator = A.Fake();
- private readonly IChatBot chatBot = A.Fake();
+ private readonly IChatAgent chatAgent = A.Fake();
private readonly JintScriptEngine sut;
public JintScriptEngineHelperTests()
@@ -35,7 +35,7 @@ public class JintScriptEngineHelperTests : IClassFixture
new HttpJintExtension(httpClientFactory),
new StringJintExtension(),
new StringWordsJintExtension(),
- new StringAsyncJintExtension(translator, chatBot)
+ new StringAsyncJintExtension(translator, chatAgent)
};
sut = new JintScriptEngine(new MemoryCache(Options.Create(new MemoryCacheOptions())),
@@ -619,8 +619,8 @@ public class JintScriptEngineHelperTests : IClassFixture
[Fact]
public async Task Should_generate_content()
{
- A.CallTo(() => chatBot.AskQuestionAsync("prompt", A._))
- .Returns(new ChatBotResult { Choices = new List { "Generated" } });
+ A.CallTo(() => chatAgent.PromptAsync(A._, "prompt", A._))
+ .Returns(ChatBotResponse.Success("Generated"));
var vars = new ScriptVars
{
@@ -635,6 +635,9 @@ public class JintScriptEngineHelperTests : IClassFixture
var actual = await sut.ExecuteAsync(vars, script);
Assert.Equal("Generated", actual.ToString());
+
+ A.CallTo(() => chatAgent.StopConversationAsync(A._, A._))
+ .MustHaveHappened();
}
[Theory]
@@ -657,7 +660,10 @@ public class JintScriptEngineHelperTests : IClassFixture
Assert.Equal(JsonValue.Null, actual);
- A.CallTo(() => chatBot.AskQuestionAsync(A._, A._))
+ A.CallTo(() => chatAgent.PromptAsync(A._, A._, A._))
+ .MustNotHaveHappened();
+
+ A.CallTo(() => chatAgent.StopConversationAsync(A._, A._))
.MustNotHaveHappened();
}
diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj b/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj
index d0c2147fa..8a6c45d14 100644
--- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj
+++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Squidex.Domain.Apps.Core.Tests.csproj
@@ -16,19 +16,19 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs
index b1c402935..c7f9cd338 100644
--- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs
+++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs
@@ -163,7 +163,7 @@ public abstract class GraphQLTestBase : IClassFixture
return A.That.Matches(x =>
x.App == TestApp.Default &&
x.NoCleanup() &&
- x.NoAssetEnrichment());
+ !x.NoAssetEnrichment());
}
protected static Context MatchsContentContext()
diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj
index 607773f04..cbc60562a 100644
--- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj
+++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj
@@ -24,24 +24,24 @@
-
-
+
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj b/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj
index 00edd3e24..e53f2366a 100644
--- a/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj
+++ b/backend/tests/Squidex.Domain.Users.Tests/Squidex.Domain.Users.Tests.csproj
@@ -16,15 +16,15 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj b/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
index 905a2660e..8fcd48eef 100644
--- a/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
+++ b/backend/tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
@@ -16,7 +16,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -24,12 +24,12 @@
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj b/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj
index f77956452..14f5b5c32 100644
--- a/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj
+++ b/backend/tests/Squidex.Web.Tests/Squidex.Web.Tests.csproj
@@ -16,14 +16,14 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/tools/TestSuite/TestSuite.ApiTests/AssetFormatTests.cs b/tools/TestSuite/TestSuite.ApiTests/AssetFormatTests.cs
index fe6fc13ce..5ecb758fa 100644
--- a/tools/TestSuite/TestSuite.ApiTests/AssetFormatTests.cs
+++ b/tools/TestSuite/TestSuite.ApiTests/AssetFormatTests.cs
@@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
+using Squidex.Assets;
using Squidex.ClientLibrary;
using TestSuite.Fixtures;
@@ -60,7 +61,7 @@ public class AssetFormatTests : IClassFixture
[Fact]
public async Task Should_upload_image_jpg_and_resize()
{
- var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_62kb.jpg", "image/jpg");
+ var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_62kb.jpg", "image/jpeg");
await AssertImageAsync(asset);
@@ -70,7 +71,7 @@ public class AssetFormatTests : IClassFixture
[Fact]
public async Task Should_upload_image_webp_and_resize()
{
- var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_100kb.webp", "image/jpg");
+ var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_100kb.webp", "image/jpeg");
await AssertImageAsync(asset);
}
@@ -78,7 +79,7 @@ public class AssetFormatTests : IClassFixture
[Fact]
public async Task Should_upload_image_tiff_and_resize()
{
- var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_400kb.tiff", "image/jpg");
+ var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_400kb.tiff", "image/jpeg");
await AssertImageAsync(asset);
}
@@ -112,6 +113,25 @@ public class AssetFormatTests : IClassFixture
await Verify(asset);
}
+ [Fact]
+ public async Task Should_upload_image_and_remove_location()
+ {
+ var asset = await _.Client.Assets.UploadFileAsync("Assets/SampleImage_WithLocation.jpg", "image/jpeg");
+
+ var url = _.Client.GenerateImageUrl(asset.Id);
+
+ var httpClient = _.Client.CreateHttpClient();
+ var httpResonse = await httpClient.GetAsync(url);
+
+ await using (var stream = await httpResonse.Content.ReadAsStreamAsync())
+ {
+ var imageLoader = new ImageSharpThumbnailGenerator();
+ var imageInfo = await imageLoader.GetImageInfoAsync(stream, "image/jpeg");
+
+ Assert.False(imageInfo?.HasSensitiveMetadata);
+ }
+ }
+
private async Task AssertImageAsync(AssetDto asset)
{
await Verify(asset);
@@ -132,7 +152,7 @@ public class AssetFormatTests : IClassFixture
[Fact]
public async Task Should_fix_orientation()
{
- var asset = await _.Client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg");
+ var asset = await _.Client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpeg");
// Should parse image metadata and fix orientation.
Assert.True(asset.IsImage);
@@ -218,10 +238,9 @@ public class AssetFormatTests : IClassFixture
var url = $"{_.Client.GenerateImageUrl(imageId)}?width={width}&height={height}";
var httpClient = _.Client.CreateHttpClient();
+ var httpResponse = await httpClient.GetAsync(url);
- var response = await httpClient.GetAsync(url);
-
- await using (var stream = await response.Content.ReadAsStreamAsync())
+ await using (var stream = await httpResponse.Content.ReadAsStreamAsync())
{
var buffer = new MemoryStream();
@@ -236,16 +255,15 @@ public class AssetFormatTests : IClassFixture
var url = $"{_.Client.GenerateImageUrl(imageId)}?format={format}";
var httpClient = _.Client.CreateHttpClient();
+ var httpResponse = await httpClient.GetAsync(url);
- var response = await httpClient.GetAsync(url);
-
- await using (var stream = await response.Content.ReadAsStreamAsync())
+ await using (var stream = await httpResponse.Content.ReadAsStreamAsync())
{
var buffer = new MemoryStream();
await stream.CopyToAsync(buffer);
- return (buffer.Length, response.Content.Headers.ContentType?.ToString());
+ return (buffer.Length, httpResponse.Content.Headers.ContentType?.ToString());
}
}
}
diff --git a/tools/TestSuite/TestSuite.ApiTests/AssetScriptingTests.cs b/tools/TestSuite/TestSuite.ApiTests/AssetScriptingTests.cs
index 67f94c944..1dc0f0f3c 100644
--- a/tools/TestSuite/TestSuite.ApiTests/AssetScriptingTests.cs
+++ b/tools/TestSuite/TestSuite.ApiTests/AssetScriptingTests.cs
@@ -31,7 +31,7 @@ public class AssetScriptingTests : IClassFixture
var scriptRequest = new UpdateAssetScriptsDto
{
Create = @"
- if (ctx.command.mimeType == 'image/jpg') {
+ if (ctx.command.mimeType == 'image/jpeg') {
disallow('We do not use jpeg anymore.');
}"
};
@@ -40,7 +40,7 @@ public class AssetScriptingTests : IClassFixture
// STEP 1: Upload jpeg.
- var ex = await Assert.ThrowsAnyAsync(() => client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg"));
+ var ex = await Assert.ThrowsAnyAsync(() => client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpeg"));
Assert.Contains("We do not use jpeg anymore.", ex.ToString(), StringComparison.Ordinal);
}
@@ -64,7 +64,7 @@ public class AssetScriptingTests : IClassFixture
// STEP 1: Upload jpeg.
- var asset = await client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg");
+ var asset = await client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpeg");
Assert.Equal("value1", asset.Metadata["key1"]);
Assert.Equal("value2", asset.Metadata["key2"]);
@@ -81,7 +81,7 @@ public class AssetScriptingTests : IClassFixture
var scriptRequest = new UpdateAssetScriptsDto
{
Update = @"
- if (ctx.command.mimeType == 'image/jpg') {
+ if (ctx.command.mimeType == 'image/jpeg') {
disallow('We do not use jpeg anymore.');
}"
};
@@ -94,7 +94,7 @@ public class AssetScriptingTests : IClassFixture
// STEP 2: Upload jpeg.
- var ex = await Assert.ThrowsAnyAsync(() => client.Assets.ReplaceFileAsync(asset_0.Id, "Assets/logo-wide-rotated.jpg", "image/jpg"));
+ var ex = await Assert.ThrowsAnyAsync(() => client.Assets.ReplaceFileAsync(asset_0.Id, "Assets/logo-wide-rotated.jpg", "image/jpeg"));
Assert.Contains("We do not use jpeg anymore.", ex.ToString(), StringComparison.Ordinal);
}
@@ -120,7 +120,7 @@ public class AssetScriptingTests : IClassFixture
// STEP 2: Upload jpeg.
- var asset = await client.Assets.ReplaceFileAsync(asset_0.Id, "Assets/logo-wide-rotated.jpg", "image/jpg");
+ var asset = await client.Assets.ReplaceFileAsync(asset_0.Id, "Assets/logo-wide-rotated.jpg", "image/jpeg");
Assert.Equal("value1", asset.Metadata["key1"]);
Assert.Equal("value2", asset.Metadata["key2"]);
@@ -135,7 +135,7 @@ public class AssetScriptingTests : IClassFixture
var scriptRequest = new UpdateAssetScriptsDto
{
Query = @"
- if (ctx.asset.mimeType == 'image/jpg') {
+ if (ctx.asset.mimeType == 'image/jpeg') {
disallow('We do not use jpeg anymore.');
}"
};
@@ -144,7 +144,7 @@ public class AssetScriptingTests : IClassFixture
// STEP 1. Upload initial jpg.
- var ex = await Assert.ThrowsAnyAsync(() => client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg"));
+ var ex = await Assert.ThrowsAnyAsync(() => client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpeg"));
Assert.Contains("We do not use jpeg anymore.", ex.ToString(), StringComparison.Ordinal);
}
diff --git a/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_100kb.webp b/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_100kb.webp
index e91c03168..9c132d821 100644
Binary files a/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_100kb.webp and b/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_100kb.webp differ
diff --git a/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_WithLocation.jpg b/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_WithLocation.jpg
new file mode 100644
index 000000000..4a2c1552b
Binary files /dev/null and b/tools/TestSuite/TestSuite.ApiTests/Assets/SampleImage_WithLocation.jpg differ
diff --git a/tools/TestSuite/TestSuite.ApiTests/ContentLanguageTests.cs b/tools/TestSuite/TestSuite.ApiTests/ContentLanguageTests.cs
index 014534d09..ddb5b8b2a 100644
--- a/tools/TestSuite/TestSuite.ApiTests/ContentLanguageTests.cs
+++ b/tools/TestSuite/TestSuite.ApiTests/ContentLanguageTests.cs
@@ -122,8 +122,8 @@ public class ContentLanguageTests : IClassFixture
httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value);
}
- var response = await httpClient.GetAsync(url);
+ var httpResponse = await httpClient.GetAsync(url);
- return (response.Headers.GetValues("ETag").FirstOrDefault(), response.Headers.Vary.ToString());
+ return (httpResponse.Headers.GetValues("ETag").FirstOrDefault(), httpResponse.Headers.Vary.ToString());
}
}
diff --git a/tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs b/tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs
index d0eb405f1..78b0efda4 100644
--- a/tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs
+++ b/tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs
@@ -7,6 +7,7 @@
using System.Net.Http.Json;
using FluentAssertions;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Utils;
@@ -26,6 +27,71 @@ public sealed class GraphQLTests : IClassFixture
_ = fixture;
}
+ [Fact]
+ public async Task Should_query_assets()
+ {
+ var asset = await _.Client.Assets.UploadFileAsync("Assets/logo-squared.png", "image/png");
+
+ var query = new
+ {
+ query = @"
+ query FindAsset($id: String!) {
+ findAsset(id: $id) {
+ id
+ version
+ created
+ createdBy
+ createdByUser {
+ id
+ email
+ displayName
+ }
+ editToken
+ lastModified
+ lastModifiedBy
+ lastModifiedByUser {
+ id
+ email
+ displayName
+ }
+ url
+ thumbnailUrl
+ mimeType
+ fileName
+ fileHash
+ fileSize
+ fileVersion
+ isImage
+ isProtected
+ pixelWidth
+ pixelHeight
+ parentId
+ tags
+ type
+ metadataText
+ metadataPixelWidth: metadata(path: ""pixelWidth"")
+ metadataUnknown: metadata(path: ""unknown"")
+ metadata
+ slug
+ }
+ }",
+ variables = new
+ {
+ id = asset.Id,
+ }
+ };
+
+ var result = await _.Client.SharedDynamicContents.GraphQlAsync(query);
+
+ var settings = new VerifySettings();
+ settings.IgnoreMember("editToken");
+ settings.IgnoreMember("thumbnailUrl");
+ settings.IgnoreMember("url");
+ settings.IgnoreMember("version");
+
+ await VerifyJson(JsonConvert.SerializeObject(result), settings);
+ }
+
[Fact]
public async Task Should_query_json()
{
@@ -342,12 +408,13 @@ public sealed class GraphQLTests : IClassFixture
}"
};
- var httpClient = _.Client.CreateHttpClient();
+ var url = _.Client.GenerateUrl($"api/content/{_.AppName}/graphql/batch");
// Create the request manually to check the content type.
- var response = await httpClient.PostAsync(_.Client.GenerateUrl($"api/content/{_.AppName}/graphql/batch"), query.ToContent(_.Client.Options));
+ var httpClient = _.Client.CreateHttpClient();
+ var httpResponse = await httpClient.PostAsync(url, query.ToContent(_.Client.Options));
- Assert.Equal("application/json", response.Content.Headers.ContentType?.MediaType);
+ Assert.Equal("application/json", httpResponse.Content.Headers.ContentType?.MediaType);
}
[Fact]
@@ -445,10 +512,9 @@ public sealed class GraphQLTests : IClassFixture
}"
};
- var httpClient = _.Client.CreateHttpClient();
-
// Create the request manually to check the headers.
- var response = await httpClient.PostAsJsonAsync($"api/content/{_.AppName}/graphql", query);
+ var httpClient = _.Client.CreateHttpClient();
+ var httpResponse = await httpClient.PostAsJsonAsync($"api/content/{_.AppName}/graphql", query);
Assert.Equal(new[]
{
@@ -462,6 +528,6 @@ public sealed class GraphQLTests : IClassFixture
"X-ResolveFlow",
"X-ResolveUrls",
"X-Unpublished"
- }, response.Headers.Vary.Order().ToArray());
+ }, httpResponse.Headers.Vary.Order().ToArray());
}
}
diff --git a/tools/TestSuite/TestSuite.ApiTests/StatisticsTests.cs b/tools/TestSuite/TestSuite.ApiTests/StatisticsTests.cs
index a8ce093b6..6f22b2eb3 100644
--- a/tools/TestSuite/TestSuite.ApiTests/StatisticsTests.cs
+++ b/tools/TestSuite/TestSuite.ApiTests/StatisticsTests.cs
@@ -31,11 +31,10 @@ public class StatisticsTests : IClassFixture
// STEP 2: Download log.
var httpClient = _.Client.CreateHttpClient();
+ var httpResponse = await httpClient.GetAsync(log.DownloadUrl);
- var response = await httpClient.GetAsync(log.DownloadUrl);
-
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- Assert.Equal("text/csv", response.Content.Headers.GetValues("Content-Type").First());
+ Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode);
+ Assert.Equal("text/csv", httpResponse.Content.Headers.GetValues("Content-Type").First());
}
[Fact]
diff --git a/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj b/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj
index c50c3cebd..4da9f69aa 100644
--- a/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj
+++ b/tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj
@@ -11,18 +11,19 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers
@@ -76,6 +77,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_fix_orientation.verified.txt b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_fix_orientation.verified.txt
index e0fcca598..4ae20ba45 100644
--- a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_fix_orientation.verified.txt
+++ b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_fix_orientation.verified.txt
@@ -2,12 +2,12 @@
Id: Guid_1,
ParentId: Guid_Empty,
FileName: logo-wide-rotated.jpg,
- FileHash: TLNAlI4UM3i8O4IF/O7ZuH3PrI3+bsz4AsBt9NrEydI=,
+ FileHash: XFoH3mp4QW9EIWjF50vJkm8IwnrjjO+ZiqV2GnH1GGw=,
IsProtected: false,
Slug: logo-wide-rotated.jpg,
- MimeType: image/jpg,
+ MimeType: image/jpeg,
FileType: jpg,
- MetadataText: 600x135px, 15.1 kB,
+ MetadataText: 600x135px, 15.2 kB,
Metadata: {
description: JFIF File,
imageQuality: 79,
@@ -19,7 +19,7 @@
image,
image/medium
],
- FileSize: 15425,
+ FileSize: 15598,
Type: Image,
Links: {
content: {
diff --git a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_jpg_and_resize.verified.txt b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_jpg_and_resize.verified.txt
index f37fad969..480ba9f4f 100644
--- a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_jpg_and_resize.verified.txt
+++ b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_jpg_and_resize.verified.txt
@@ -2,12 +2,12 @@
Id: Guid_1,
ParentId: Guid_Empty,
FileName: SampleImage_62kb.jpg,
- FileHash: hmGXmHleJqbU37bbPExix+Jbu36GNq6ZPf09Uw63t8w=,
+ FileHash: ss/g3yq5dO3jYbWzJ9j2psJo1Nrk5TjSi78LJfCma38=,
IsProtected: false,
Slug: sampleimage-62kb.jpg,
- MimeType: image/jpg,
+ MimeType: image/jpeg,
FileType: jpg,
- MetadataText: 600x400px, 62 kB,
+ MetadataText: 600x400px, 59.2 kB,
Metadata: {
description: JFIF File,
imageQuality: 79,
@@ -19,7 +19,7 @@
image,
image/medium
],
- FileSize: 63507,
+ FileSize: 60603,
Type: Image,
Links: {
content: {
diff --git a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_tiff_and_resize.verified.txt b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_tiff_and_resize.verified.txt
index d36c9875b..750a870e8 100644
--- a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_tiff_and_resize.verified.txt
+++ b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_tiff_and_resize.verified.txt
@@ -5,7 +5,7 @@
FileHash: f+ZdTDOoK23jmThbfPhWhXL8Q9+KIQajHeFfT/MtWFU=,
IsProtected: false,
Slug: sampleimage-400kb.tiff,
- MimeType: image/jpg,
+ MimeType: image/jpeg,
FileType: tiff,
MetadataText: 600x400px, 473.6 kB,
Metadata: {
diff --git a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_webp_and_resize.verified.txt b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_webp_and_resize.verified.txt
index 3cbf0c952..d29bf5971 100644
--- a/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_webp_and_resize.verified.txt
+++ b/tools/TestSuite/TestSuite.ApiTests/Verify/AssetFormatTests.Should_upload_image_webp_and_resize.verified.txt
@@ -2,12 +2,12 @@
Id: Guid_1,
ParentId: Guid_Empty,
FileName: SampleImage_100kb.webp,
- FileHash: WwD409RVswvccG2YopnFqJzpWrCveLrd0Zj6Buw8Vao=,
+ FileHash: fH0g7j4+h2vR6q0/E3BabgDqtFk0FnDfxT/AkuHKkf8=,
IsProtected: false,
Slug: sampleimage-100kb.webp,
- MimeType: image/jpg,
+ MimeType: image/jpeg,
FileType: webp,
- MetadataText: 600x400px, 109.5 kB,
+ MetadataText: 600x400px, 37.7 kB,
Metadata: {
pixelHeight: 400,
pixelWidth: 600
@@ -17,7 +17,7 @@
image,
image/medium
],
- FileSize: 112138,
+ FileSize: 38580,
Type: Image,
Links: {
content: {
diff --git a/tools/TestSuite/TestSuite.ApiTests/Verify/GraphQLTests.Should_query_assets.verified.txt b/tools/TestSuite/TestSuite.ApiTests/Verify/GraphQLTests.Should_query_assets.verified.txt
new file mode 100644
index 000000000..3a1bf6fde
--- /dev/null
+++ b/tools/TestSuite/TestSuite.ApiTests/Verify/GraphQLTests.Should_query_assets.verified.txt
@@ -0,0 +1,44 @@
+{
+ findAsset: {
+ id: Guid_1,
+ created: DateTimeOffset_1,
+ createdBy: client:root,
+ createdByUser: {
+ id: root,
+ email: client:root,
+ displayName: root
+ },
+ lastModified: DateTimeOffset_1,
+ lastModifiedBy: client:root,
+ lastModifiedByUser: {
+ id: root,
+ email: client:root,
+ displayName: root
+ },
+ mimeType: image/png,
+ fileName: logo-squared.png,
+ fileHash: pAp0RDvipkoNCCTgey1HTJekRKKEWT6Ft5JdRLuAfAc=,
+ fileSize: 19430,
+ fileVersion: 0,
+ isImage: true,
+ isProtected: false,
+ pixelWidth: 600,
+ pixelHeight: 600,
+ parentId: Guid_Empty,
+ tags: [
+ type/png,
+ image,
+ image/medium
+ ],
+ type: IMAGE,
+ metadataText: 600x600px, 19 kB,
+ metadataPixelWidth: 600,
+ metadataUnknown: null,
+ metadata: {
+ pixelWidth: 600,
+ pixelHeight: 600,
+ description: PNG File
+ },
+ slug: logo-squared.png
+ }
+}
\ No newline at end of file