From 308f013ad134d2ed12e87bb614c0fb9951d33b0e Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 6 Sep 2026 22:51:17 -0700 Subject: [PATCH] test(workflows-api): pin that a new read-only workflow can be imported (#8038) Add regression coverage for both the single and bulk import endpoints confirming that importing a workflow definition with a fresh DefinitionId and IsReadonly=true succeeds and persists as read-only. NotReadOnlyPolicy is only meant to block edits of existing read-only workflows; on main it already resolves against the stored definition (null for a new one), so these tests pin that behavior against regression. Refs #7981 Co-authored-by: Claude Fable 5.1 --- .../Import/ImportAuthorizationTests.cs | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/RestApis/Endpoints/WorkflowDefinitions/Import/ImportAuthorizationTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/RestApis/Endpoints/WorkflowDefinitions/Import/ImportAuthorizationTests.cs index 611b389bd..94d19bd7f 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/RestApis/Endpoints/WorkflowDefinitions/Import/ImportAuthorizationTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/RestApis/Endpoints/WorkflowDefinitions/Import/ImportAuthorizationTests.cs @@ -64,6 +64,34 @@ public class ImportAuthorizationTests : AppComponentTest await AssertDefinitionUnchangedAsync(readOnlyDefinitionId, "ReadOnly Original", isReadonly: true); } + [Fact] + public async Task ImportNewReadOnlyDefinition_ShouldSucceedAndPersistAsReadOnly() + { + var definitionId = $"new-readonly-import-{Guid.NewGuid():N}"; + + var importedDefinition = await _client.ImportAsync(CreateImportModel(definitionId, "New ReadOnly", isReadonly: true)); + + Assert.True(importedDefinition.IsReadonly); + await AssertDefinitionUnchangedAsync(definitionId, "New ReadOnly", isReadonly: true); + } + + [Fact] + public async Task ImportFilesWithNewReadOnlyDefinition_ShouldSucceedAndPersistAsReadOnly() + { + var definitionId = $"new-readonly-import-files-{Guid.NewGuid():N}"; + + await using var stream = CreateImportStream(definitionId, "New ReadOnly", isReadonly: true); + var files = new List + { + new(stream, "readonly.json", "application/json") + }; + + var response = await _client.ImportFilesAsync(files); + + Assert.Equal(1, response.Count); + await AssertDefinitionUnchangedAsync(definitionId, "New ReadOnly", isReadonly: true); + } + private async Task SaveDefinitionAsync(string definitionId, string name, bool isReadonly = false) { await _store.SaveAsync(new WorkflowDefinitionEntity @@ -91,18 +119,19 @@ public class ImportAuthorizationTests : AppComponentTest Assert.Equal(isReadonly, definition.IsReadonly); } - private static WorkflowDefinitionModel CreateImportModel(string definitionId, string name) + private static WorkflowDefinitionModel CreateImportModel(string definitionId, string name, bool isReadonly = false) { return new() { DefinitionId = definitionId, - Name = name + Name = name, + IsReadonly = isReadonly }; } - private static MemoryStream CreateImportStream(string definitionId, string name) + private static MemoryStream CreateImportStream(string definitionId, string name, bool isReadonly = false) { - var json = JsonSerializer.Serialize(CreateImportModel(definitionId, name), new JsonSerializerOptions(JsonSerializerDefaults.Web)); + var json = JsonSerializer.Serialize(CreateImportModel(definitionId, name, isReadonly), new JsonSerializerOptions(JsonSerializerDefaults.Web)); return new(Encoding.UTF8.GetBytes(json)); } }