Files
ClawdDotNet/tests/ClawdDotNet.Core.Tests/Tasks/TaskboardAusbauTests.cs
T
RichardandClaude Opus 5.5 837a634a22 Stufe 4c (#764): Kommentare in C#, WebUI-Skripten, CSS und HTML auf Englisch
Rund 2.600 Kommentarblöcke in 310 C#-Dateien übersetzt, Begründungen vollständig
erhalten: blockweise gleiche Anzahl wie vorher, kein Block unter 60 % seiner
Länge, der Code außerhalb der Kommentare per Tokenizer byte-identisch geprüft.
Zitate deutscher Oberflächentexte und Testdaten bleiben deutsch.

WebUI: Kommentare in JS/CSS/HTML übersetzt, JSDoc-@param an die in 4b
umbenannten Parameter angeglichen.

Dabei behoben:
- 4b hatte "tag" (HTML-Tag) als deutsches "Tag" gelesen und zu "dayValue"
  gemacht (makeElement, svg, Tagesübersicht) - zurück auf tag/day.
- Aufgaben "InProgress" bekamen die Plakettenart "laufend", für die es nie eine
  CSS-Klasse gab - jetzt "success" wie laufende Instanzen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:45:03 +02:00

110 lines
4.3 KiB
C#

using ClawdDotNet.Core.Tasks;
using Shouldly;
namespace ClawdDotNet.Core.Tests.Tasks;
/// <summary>
/// Checking schedules, next run and runs per day (#594, #595, #597) as well as the hint
/// about growing context (#598).
/// </summary>
public sealed class TaskboardAusbauTests
{
private static DateTime Utc(int y, int mo, int d, int h, int mi) => new(y, mo, d, h, mi, 0, DateTimeKind.Utc);
private static TaskWhen Cron(string value, string tz = "Europe/Berlin")
=> new() { Kind = TaskWhenKind.Cron, Value = value, TimeZone = tz };
// ─── #597 checking schedules ───
[Fact]
public void Gueltiger_Termin_mit_Bereich_und_Schritt_besteht_die_Pruefung()
=> TaskSchedule.ValidateWhen(Cron("0 7-22/3 * * *")).ShouldBeNull();
[Fact]
public void Kaputter_Cron_Ausdruck_wird_benannt()
=> TaskSchedule.ValidateWhen(Cron("0 7-22/x * * *")).ShouldNotBeNull().ShouldContain("'x' ist keine Zahl");
[Fact]
public void Unbekannte_Zeitzone_wird_benannt()
=> TaskSchedule.ValidateWhen(Cron("0 9 * * *", "Phantasie/Ort")).ShouldNotBeNull().ShouldContain("Phantasie/Ort");
[Theory]
[InlineData(TaskWhenKind.Every, "30m", true)]
[InlineData(TaskWhenKind.Every, "halbstündlich", false)]
[InlineData(TaskWhenKind.At, "2026-09-15T08:00", true)]
[InlineData(TaskWhenKind.At, "morgen früh", false)]
public void Intervall_und_Zeitpunkt_werden_geprueft(TaskWhenKind kind, string value, bool gueltig)
=> (TaskSchedule.ValidateWhen(new TaskWhen { Kind = kind, Value = value, TimeZone = "Europe/Berlin" }) is null)
.ShouldBe(gueltig);
// ─── #594 next run ───
[Fact]
public void Naechster_Lauf_eines_Cron_Termins_in_Berliner_Zeit()
{
var task = new TaskItem { Id = "t-7e0bbe", When = Cron("0 7-22/3 * * *") };
// 12:30 Berlin (CEST) -> next occurrence 13:00 Berlin = 11:00 UTC
TaskSchedule.NextOccurrenceUtc(task, Utc(2026, 9, 14, 10, 30)).ShouldBe(Utc(2026, 9, 14, 11, 0));
}
[Fact]
public void Naechster_Lauf_eines_Intervalls_zaehlt_ab_dem_letzten_Lauf()
{
var task = new TaskItem
{
Id = "t-1",
When = new TaskWhen { Kind = TaskWhenKind.Every, Value = "2h", TimeZone = "" },
LastOccurrence = "2026-09-14T09:00:00.0000000Z"
};
TaskSchedule.NextOccurrenceUtc(task, Utc(2026, 9, 14, 10, 0)).ShouldBe(Utc(2026, 9, 14, 11, 0));
}
[Fact]
public void Einmalige_Aufgabe_steht_an_bis_sie_lief()
{
var jetzt = Utc(2026, 9, 14, 10, 0);
TaskSchedule.NextOccurrenceUtc(new TaskItem { Id = "t-1" }, jetzt).ShouldBe(jetzt);
TaskSchedule.NextOccurrenceUtc(new TaskItem { Id = "t-1", LastOccurrence = "x" }, jetzt).ShouldBeNull();
}
// ─── #595 runs per day ───
[Fact]
public void Laeufe_je_Tag_aus_Cron_und_Intervall()
{
var jetzt = Utc(2026, 9, 14, 10, 0);
TaskSchedule.RunsPerDay(new TaskItem { When = Cron("0 7-22/3 * * *") }, jetzt).ShouldBe(6);
TaskSchedule.RunsPerDay(new TaskItem { When = Cron("5 * * * *") }, jetzt).ShouldBe(24);
TaskSchedule.RunsPerDay(new TaskItem { When = new TaskWhen { Kind = TaskWhenKind.Every, Value = "30m" } }, jetzt).ShouldBe(48);
TaskSchedule.RunsPerDay(new TaskItem(), jetzt).ShouldBe(0);
}
// ─── #598 hint ───
[Fact]
public void Wiederkehrend_im_Chatverlauf_bekommt_den_Hinweis()
=> TaskHinweise.WachsenderKontext(new TaskItem { Assignee = "@nachrichten", When = Cron("0 7-22/3 * * *") })
.ShouldNotBeNull().ShouldContain("@new:nachrichten");
[Theory]
[InlineData("@new:nachrichten", true)]
[InlineData("@nachrichten", false)]
[InlineData("@human", true)]
public void Kein_Hinweis_fuer_frische_Laeufe_einmalige_und_menschliche_Aufgaben(string assignee, bool wiederkehrend)
=> TaskHinweise.WachsenderKontext(new TaskItem
{
Assignee = assignee,
When = wiederkehrend ? Cron("5 * * * *") : null
}).ShouldBeNull();
[Fact]
public void Kein_Hinweis_fuer_Werkzeugjobs()
=> TaskHinweise.WachsenderKontext(new TaskItem
{
Assignee = "@telegram", Type = TaskItemType.ToolJob, When = Cron("* * * * *")
}).ShouldBeNull();
}