Files
nexus/backend-tests/TaskBoardTests.cs
T
devops 83e072bc27
CI - Build & Test / Backend (.NET) (push) Successful in 29s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 19s
CI - Build & Test / Security Check (push) Successful in 4s
feat: Bao/Iris-Statusrechte + Bao→Iris-Notifications + Agent-Workflow-Übersicht
- Bao darf jetzt Status ändern (neben Iris), Sub-Agents weiterhin nicht
- CanEditContent für Inhaltsbearbeitung durch alle bekannten Caller
- Bao-Content-Änderungen triggern task_content_changed-Notification an Iris
- Bao-Status-Änderungen triggern task_status_changed-Notification an Iris
- Iris-Status-Änderungen triggern task_status_changed-Notification an Bao
- Neue WorkTask-Felder: IsAgentTask (bool), ExpectedFrom (string)
- Agent-Workflow-API: CreateAgentTask, WaitingTasks, AgentOverview
- Frontend: Agent-Task-Badge, Iris-Overview-Panel, isBao-Getter
- Login-Rate-Limiter mit strukturiertem JSON-Fehlermeldungs-Body
- Volume-Name: nexus-postgres → postgres-data (Standardisierung)
2026-06-20 18:43:05 +02:00

254 lines
8.3 KiB
C#

using Nexus.Api.Data;
using Xunit;
namespace Nexus.Api.Tests;
public class TaskBoardTests
{
// ── TaskStateHelper: BoardGroupKey ──
[Theory]
[InlineData("Backlog", "offen")]
[InlineData("In progress", "inProgress")]
[InlineData("Delegated", "delegated")]
[InlineData("Review", "review")]
[InlineData("Blocked", "blocked")]
[InlineData("Done", "done")]
[InlineData("backlog", "offen")]
[InlineData("in progress", "inProgress")]
[InlineData("delegated", "delegated")]
[InlineData("review", "review")]
[InlineData("blocked", "blocked")]
[InlineData("done", "done")]
[InlineData("", "offen")]
[InlineData(null, "offen")]
[InlineData("unknown", "offen")]
public void BoardGroupKey_ReturnsExpectedGroup(string? state, string expected)
{
var result = TaskStateHelper.BoardGroupKey(state);
Assert.Equal(expected, result);
}
// ── TaskStateHelper: BoardGroupToState ──
[Theory]
[InlineData("offen", "Backlog")]
[InlineData("inProgress", "In progress")]
[InlineData("inprogress", "In progress")]
[InlineData("delegated", "Delegated")]
[InlineData("review", "Review")]
[InlineData("blocked", "Blocked")]
[InlineData("done", "Done")]
[InlineData("Offen", "Backlog")]
[InlineData("", null)]
[InlineData(null, null)]
[InlineData("unknown", null)]
public void BoardGroupToState_ReturnsExpectedState(string? groupKey, string? expected)
{
var result = TaskStateHelper.BoardGroupToState(groupKey);
Assert.Equal(expected, result);
}
// ── TaskStateHelper: AllStates has 6 entries ──
[Fact]
public void AllStates_ContainsAllSixStates()
{
var states = TaskStateHelper.AllStates;
Assert.Equal(6, states.Length);
Assert.Contains("Backlog", states);
Assert.Contains("In progress", states);
Assert.Contains("Delegated", states);
Assert.Contains("Review", states);
Assert.Contains("Blocked", states);
Assert.Contains("Done", states);
}
// ── TaskStateHelper: IsValidState ──
[Theory]
[InlineData("Backlog", true)]
[InlineData("In progress", true)]
[InlineData("Delegated", true)]
[InlineData("Review", true)]
[InlineData("Blocked", true)]
[InlineData("Done", true)]
[InlineData("backlog", true)]
[InlineData("offen", false)]
[InlineData("", false)]
[InlineData(null, false)]
[InlineData("unknown", false)]
public void IsValidState_ReturnsCorrectResult(string? state, bool expected)
{
Assert.Equal(expected, TaskStateHelper.IsValidState(state));
}
// ── TaskStateHelper: IsInProgressOrBlocked ──
[Theory]
[InlineData("In progress", true)]
[InlineData("Blocked", true)]
[InlineData("Backlog", false)]
[InlineData("Delegated", false)]
[InlineData("Review", false)]
[InlineData("Done", false)]
[InlineData(null, false)]
public void IsInProgressOrBlocked_ReturnsCorrectResult(string? state, bool expected)
{
Assert.Equal(expected, TaskStateHelper.IsInProgressOrBlocked(state));
}
// ── TaskStateHelper: IsDoneOrBacklog ──
[Theory]
[InlineData("Done", true)]
[InlineData("Backlog", true)]
[InlineData("In progress", false)]
[InlineData("Delegated", false)]
[InlineData("Review", false)]
[InlineData("Blocked", false)]
[InlineData(null, false)]
public void IsDoneOrBacklog_ReturnsCorrectResult(string? state, bool expected)
{
Assert.Equal(expected, TaskStateHelper.IsDoneOrBacklog(state));
}
// ── TaskStateHelper: ToDisplayString ──
[Theory]
[InlineData("Backlog", "Offen")]
[InlineData("In progress", "In Bearbeitung")]
[InlineData("Delegated", "Delegiert")]
[InlineData("Review", "Review")]
[InlineData("Blocked", "Blockiert")]
[InlineData("Done", "Erledigt")]
[InlineData("backlog", "Offen")]
[InlineData("", "")]
[InlineData(null, "")]
[InlineData("unknown", "unknown")]
public void ToDisplayString_ReturnsGermanLabel(string? state, string expected)
{
Assert.Equal(expected, TaskStateHelper.ToDisplayString(state));
}
// ── TaskState helper: ToStateString and ToTaskState roundtrip ──
[Fact]
public void ToStateString_And_ToTaskState_RoundTrip()
{
var states = new[] { TaskState.Backlog, TaskState.InProgress, TaskState.Delegated, TaskState.Review, TaskState.Blocked, TaskState.Done };
foreach (var state in states)
{
var str = state.ToStateString();
var parsed = str.ToTaskState();
Assert.Equal(state, parsed);
}
}
[Fact]
public void ToTaskState_DefaultsToBacklog_ForUnknownString()
{
Assert.Equal(TaskState.Backlog, "unknown".ToTaskState());
}
// ── TaskStateHelper: CanChangeState (Iris + Bao policy) ──
[Fact]
public void CanChangeState_Iris_CanChangeAnyTask()
{
var agentTask = new WorkTask { Title = "test", IsAgentTask = true, Source = "iris" };
var normalTask = new WorkTask { Title = "test", IsAgentTask = false, Source = "bao" };
Assert.True(TaskStateHelper.CanChangeState("iris", agentTask));
Assert.True(TaskStateHelper.CanChangeState("iris", normalTask));
}
[Fact]
public void CanChangeState_Bao_CanChangeAnyTask()
{
var agentTask = new WorkTask { Title = "test", IsAgentTask = true, Source = "iris" };
var normalTask = new WorkTask { Title = "test", IsAgentTask = false, Source = "bao" };
Assert.True(TaskStateHelper.CanChangeState("bao", agentTask));
Assert.True(TaskStateHelper.CanChangeState("bao", normalTask));
}
[Fact]
public void CanChangeState_SubAgents_NeverAllowed()
{
var task = new WorkTask { Title = "test", IsAgentTask = false, Source = "bao" };
Assert.False(TaskStateHelper.CanChangeState("programmer", task));
Assert.False(TaskStateHelper.CanChangeState("reviewer", task));
Assert.False(TaskStateHelper.CanChangeState("architekt", task));
}
[Fact]
public void CanChangeState_SubAgents_NeverAllowed_EvenForAgentTasks()
{
var agentTask = new WorkTask { Title = "test", IsAgentTask = true, Source = "iris" };
Assert.False(TaskStateHelper.CanChangeState("programmer", agentTask));
Assert.False(TaskStateHelper.CanChangeState("reviewer", agentTask));
Assert.False(TaskStateHelper.CanChangeState("architekt", agentTask));
}
[Fact]
public void CanChangeState_NexusSystem_IsAllowed()
{
var task = new WorkTask { Title = "test", IsAgentTask = false };
Assert.True(TaskStateHelper.CanChangeState("nexus-system", task));
var agentTask = new WorkTask { Title = "test", IsAgentTask = true };
Assert.True(TaskStateHelper.CanChangeState("nexus-system", agentTask));
}
[Fact]
public void CanChangeState_UnknownCaller_Rejected()
{
var task = new WorkTask { Title = "test", IsAgentTask = false };
var agentTask = new WorkTask { Title = "test", IsAgentTask = true };
Assert.False(TaskStateHelper.CanChangeState("", task));
Assert.False(TaskStateHelper.CanChangeState("", agentTask));
Assert.False(TaskStateHelper.CanChangeState("unknown", task));
Assert.False(TaskStateHelper.CanChangeState(null, task));
}
// ── TaskStateHelper: CanEditContent ──
[Fact]
public void CanEditContent_Iris_IsAllowed()
{
Assert.True(TaskStateHelper.CanEditContent("iris"));
}
[Fact]
public void CanEditContent_Bao_IsAllowed()
{
Assert.True(TaskStateHelper.CanEditContent("bao"));
}
[Fact]
public void CanEditContent_SubAgents_AreAllowed()
{
Assert.True(TaskStateHelper.CanEditContent("programmer"));
Assert.True(TaskStateHelper.CanEditContent("reviewer"));
Assert.True(TaskStateHelper.CanEditContent("architekt"));
}
[Fact]
public void CanEditContent_NexusSystem_IsAllowed()
{
Assert.True(TaskStateHelper.CanEditContent("nexus-system"));
}
[Fact]
public void CanEditContent_UnknownCaller_Rejected()
{
Assert.False(TaskStateHelper.CanEditContent(""));
Assert.False(TaskStateHelper.CanEditContent(null));
Assert.False(TaskStateHelper.CanEditContent(" "));
}
}