elsa-core/test/unit/Elsa.Labels.UnitTests/Entities/LabelNameMaxLengthTests.cs

28 lines
779 B
C#
Raw Permalink Normal View History

fix(labels): enforce per-tenant uniqueness on NormalizedName (#8112) * fix(labels): enforce per-tenant uniqueness on NormalizedName Finish the unused Label.NormalizedName contract the same way Secrets does: unique (TenantId, NormalizedName) in EF, fail-closed Memory saves, and keep NormalizedName in sync with Name. Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com> * fix(labels): clone Memory label reads so a rejected rename cannot persist Find/List handed out live store refs. Labels.Update mutates Name (and NormalizedName) on that instance before Save; a uniqueness rejection then left the stored row already renamed. Clone-on-read matches Memory identity stores from #8108. Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com> * fix(labels): stamp null TenantId, fail-loud on leftover duplicates, cap names at 255 Follow the Architect steer for Greptile P1s: do not auto-delete duplicate labels; UPDATE Labels SET TenantId = '' WHERE TenantId IS NULL on every provider before CreateIndex; keep SQL Server/Oracle filtered unique indexes; HasMaxLength(255) on Name and NormalizedName with no silent truncate. Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com> * fix(labels): fail-loud preflight for leftover keys and over-length names No silent dedupe: every provider lists leftover (TenantId, NormalizedName) keys and aborts before CreateIndex. SQL Server/Oracle keep their filtered unique indexes. PostgreSQL/SQLite keep provider column types. Providers that narrow Name/NormalizedName to 255 preflight over-length Ids first. Memory uniqueness semantics are unchanged. Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com> * test(labels): match Oracle filtered-index escape in migration assertion Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-09-13 14:16:01 +00:00
using Elsa.Labels.Entities;
namespace Elsa.Labels.UnitTests.Entities;
public class LabelNameMaxLengthTests
{
[Fact]
public void Name_WhenLongerThanSharedMaximum_Throws()
{
var label = new Label { Id = "label-1" };
var exception = Assert.Throws<ArgumentException>(() => label.Name = new string('a', Label.NameMaxLength + 1));
Assert.Equal("Name", exception.ParamName);
Assert.Contains(Label.NameMaxLength.ToString(), exception.Message);
}
[Fact]
public void Name_WhenAtSharedMaximum_Succeeds()
{
var name = new string('a', Label.NameMaxLength);
var label = new Label { Id = "label-1", Name = name };
Assert.Equal(name, label.Name);
Assert.Equal(name, label.NormalizedName);
}
}