docs: round-3 copy corrections, and pin the two behaviours nothing was guarding
Round 3's correctness/security pass came back clean; what was left said more than the code does. - emailOff promised the access-request list is where sign-ups show up. A sign-up on an address that is already approved or already pending adds nothing to it (roadmap UX-25), and "only" was falsified by this release's own inbox notice. - deleteConfirm claimed the admin was dropping "an approval you already gave" — it is the confirmation for pending and denied rows too. - sendFailed blamed the mail server for rejecting a message; the reason covers connect, DNS, TLS and login failures alike, so it now describes the symptom and leaves the diagnosis to the log. - ADMIN_EMAILS re-promotion happens in the Google callback only, not on any sign-in. Tests: the decided-list copy of the delete affordance was never rendered (both new cases fail if that branch is dropped), and the throttle release — a deliberate behaviour the notes advertise — was asserted by nothing; a drop with no admin yet, or with a failing write, must not silence the following hour.
This commit is contained in:
@@ -122,6 +122,30 @@ describe("Access requests — the delete affordance", () => {
|
||||
expect(screen.queryByLabelText(/deleteLabel/)).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps the same control on the previously-decided list, where the case is commonest", async () => {
|
||||
// The affordance exists twice — the pending rows and the collapsed "decided" list — and an
|
||||
// approved address that has since registered lands in the second one. Both must behave alike.
|
||||
listMock.mockResolvedValue([invite({ status: "approved", has_account: true })]);
|
||||
renderPanel();
|
||||
await openAccessTab();
|
||||
|
||||
fireEvent.click(await screen.findByText(/settings\.invites\.decided/));
|
||||
const btn = await screen.findByLabelText("settings.invites.deleteHasAccount");
|
||||
expect(btn.getAttribute("aria-disabled")).toBe("true");
|
||||
expect((btn as HTMLButtonElement).disabled).toBe(false);
|
||||
});
|
||||
|
||||
it("offers a working delete on a decided entry with no account", async () => {
|
||||
listMock.mockResolvedValue([invite({ status: "denied" })]);
|
||||
renderPanel();
|
||||
await openAccessTab();
|
||||
|
||||
fireEvent.click(await screen.findByText(/settings\.invites\.decided/));
|
||||
fireEvent.click(await screen.findByLabelText("settings.invites.deleteLabel:asker@example.com"));
|
||||
|
||||
await waitFor(() => expect(deleteMock).toHaveBeenCalledWith(1));
|
||||
});
|
||||
|
||||
it("warns in the confirmation — before the click is irreversible — when the env still allows it", async () => {
|
||||
listMock.mockResolvedValue([invite({ still_allowed_by_env: true })]);
|
||||
renderPanel();
|
||||
|
||||
Reference in New Issue
Block a user