feat(scheduling-webui): manage participant invitations

This commit is contained in:
2026-07-22 04:25:54 +02:00
parent fc356e22c6
commit b328df67a3
4 changed files with 384 additions and 12 deletions

View File

@@ -27,6 +27,7 @@ assert.match(page, /title=\{I18N\.invitedRequests\}/);
assert.ok(page.indexOf("title={I18N.myRequests}") < page.indexOf("title={I18N.invitedRequests}"));
assert.match(page, /<SelectionList label=\{title\} className="scheduling-request-list">/);
assert.match(page, /<SelectionListItem[\s\S]*selected=\{selectedId === request\.id\}[\s\S]*className="scheduling-list-item"/);
assert.match(page, /className="scheduling-list-item"[\s\S]{0,100}disabled=\{disabled\}/);
assert.match(page, /editorMode \? \(/);
assert.match(page, /id="scheduling-editor-form"/);
@@ -86,6 +87,26 @@ assert.match(page, /showDecisionAction=\{canManageSelected\}/);
assert.match(page, /<IconButton[\s\S]*label=\{I18N\.refresh\}/);
assert.doesNotMatch(page, /AdminIconButton/);
const participantGridStart = page.indexOf("function ParticipantsGrid(");
const participantGridEnd = page.indexOf("function invitationActionDisabledReason", participantGridStart);
const participantGrid = page.slice(participantGridStart, participantGridEnd);
assert.match(participantGrid, /\.\.\.\(canManage \? \[\{/);
assert.match(participantGrid, /minimumSlots=\{3\}/);
assert.ok(participantGrid.indexOf('id: "copy-invitation"') < participantGrid.indexOf('id: "send-invitation"'));
assert.ok(participantGrid.indexOf('id: "send-invitation"') < participantGrid.indexOf('id: "revoke-invitation"'));
assert.match(participantGrid, /schedulingInvitationActionBlocks\(request, participant, now\)/);
assert.match(participantGrid, /disabledReason: copyDisabledReason/);
assert.match(participantGrid, /disabledReason: deliveryDisabledReason/);
assert.match(participantGrid, /disabledReason: revokeDisabledReason/);
assert.match(page, /<ConfirmDialog[\s\S]*title=\{I18N\.revokeInvitationLabel\}[\s\S]*tone="danger"/);
assert.match(page, /navigator\.clipboard\.writeText\(value\)/);
assert.match(page, /navigator\.clipboard\.write\(\[new ClipboardItem/);
assert.match(page, /schedulingPublicInvitationUrl\(response\.action_url, window\.location\.origin\)/);
assert.match(page, /\["failed", "skipped"\]\.includes\(result\.status\)/);
assert.match(page, /isApiError\(err, 409\)/);
assert.match(page, /scheduleExpiryRefresh/);
assert.doesNotMatch(page, /(?:localStorage|sessionStorage).*action_url|action_url.*(?:localStorage|sessionStorage)/);
assert.match(page, /submitSchedulingAvailability\(settings, selected\.id/);
assert.match(page, /option_revision: slot\.revision/);
assert.match(page, /getSchedulingAvailabilityResponse\(settings, selected\.id\)/);
@@ -106,7 +127,8 @@ for (const field of [
"allow_comments",
"participant_email_required",
"anonymous_password_protection_enabled",
"public_participation_policy_enforcement_available"
"public_participation_policy_enforcement_available",
"participant_invitation_delivery_available"
]) {
assert.match(api, new RegExp(`${field}:`));
}
@@ -117,6 +139,9 @@ assert.match(page, /slots: slots\.map\(\(slot\) => \(\{/);
assert.match(page, /participants: participants[\s\S]*create_participant_invitations: true/);
assert.match(api, /\/api\/v1\/scheduling\/requests\/\$\{requestId\}\/responses/);
assert.match(api, /\/api\/v1\/scheduling\/requests\/\$\{requestId\}\/responses\/me/);
assert.match(api, /issueSchedulingParticipantInvitation\([\s\S]*json\(\{ action, participant_revision: participantRevision \}\)/);
assert.match(api, /revokeSchedulingParticipantInvitation\([\s\S]*method: "DELETE"[\s\S]*participant_revision: participantRevision/);
assert.match(api, /participants\/\$\{encodeURIComponent\(participantId\)\}\/invitation/);
assert.match(api, /\/api\/v1\/scheduling\/public\/\$\{encodeURIComponent\(requestId\)\}\/\$\{encodeURIComponent\(token\)\}/);
assert.match(page, /useSearchParams\(\)/);
assert.match(page, /Promise\.allSettled/);