Add the create/rename group form component #69
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/group-form"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements task 90:
GroupForm, one component for creating a group and renaming one — name only, groups have no description column (task 90's own correction).CreateGroupRequest/UpdateGroupRequest's own data annotations (task 56's pattern), no restated copy.CallerIsOwneris false, but that's a courtesy — the API's own 403 is still handled if the host's view of the role is stale.ApiProblemException.StatusCode/Errors, not by matchingDetailtext (task 155 is still open), and renders under a distinct.form-conflictclass.Navigation decision: no navigation on success. The groomed criterion ("navigates to the group detail page") predates the map becoming the home page (task 88, ADR-0059's "stay where you are"), and task 91 (group detail) hasn't been reshaped. The component raises
OnSaved(GroupResponse)and leaves what happens next to whichever page hosts it. Reasoning is onGroupForm's own XML doc.No ADR: both decisions above apply an existing one (ADR-0059's "stay put" direction; ADR-0058's status-code-not-prose pattern) rather than making a new one.
Verdict: mergeable
Verified rather than read:
CreateGroupRequest.Name's[StringLength]from 100 to 5 with no component change; the "Coffee shops" create test then correctly failed local validation and made no API call. Reverted. Confirms no restated rule.ApiProblemDetails.Errorsis populated only on the API's own 400s (per ADR-0058/ADR-0025), soErrors.Count > 0andStatusCode == Conflictcan't both misfire — the branch is sound, not just conveniently untested..form-conflictdiffers visually from.form-errorby a real border, not just a class name, and both carryrole="alert".GroupFormTests, 8 tests) passes, includingGroupForm_ApiRefusesWithForbiddenDespiteCallerIsOwner_..., which stubs a genuine 403 withCallerIsOwner: trueand asserts the general-error path renders rather than crashing or silently succeeding.IsPersonalspecial-casing anywhere inGroupForm.razor.cs;GroupForm_RenamePersonalGroupAsOwner_...exercises it directly.HttpClient:NoRawHttpClientInComponentsTestspasses against this branch, including its own non-vacuity check (WebUiSourceInsideTheApiClient_ReachesARawHttpClientSomewhere), so the guard is genuinely exercised, not merely present.global.json);PlaceMark.WebUI.Tests(155),PlaceMark.Architecture.Tests(15) andPlaceMark.Contracts.Tests(117) all pass.mainhadn't moved since the branch was cut, so no merge was needed.One non-blocking accessibility gap:
FieldErrors'<ul>carries noid, so nothing inGroupForm(orLogin/Register, which share the component) can point an input at its error viaaria-describedby— the error is proximate, not associated.role="alert"does get it announced on submit, so this isn't the mouse-only class of defect task 139 named, but a screen-reader user tabbing back to a field with an existing error won't be told why it's flagged. This is inherited from an already-merged pattern (Login/Register), not introduced here, so it doesn't block this PR — worth a follow-up ticket againstFieldErrorsitself rather than a one-off fix in this component.What bUnit cannot show: no browser was available, so the actual screen-reader announcement of
role="alert", the visual legibility of.form-conflict's border against.form-error, and any focus/keyboard behaviour are asserted from markup and CSS source only, not observed.