Align invitee separators with the server

The server splits the attendee input on whitespace, commas and
semicolons, but the search widget only treated commas and
semicolons as separators. Typing "a@x.com b" therefore sent the
whole string as the search query instead of "b", and picking a
contact dropped the whitespace-separated entry.

Split on /[\s;,]+/ in both fragment() and commit() so the
widget agrees with parseAttendees() on what an entry is.
This commit is contained in:
stefan.tollkuehn committed 2026-10-23 14:07:28 +02:00
1 parent e5432a0a38
commit 5bba3a93cd
2 files changed
+29 -2

No files matched your search

+4 -2
View File
@@ -13,7 +13,9 @@
'use strict'; 'use strict';
var DEBOUNCE_MS = 250; var DEBOUNCE_MS = 250;
var SEPARATOR = /[;,]/; /* Must match the server's attendee parsing: whitespace, comma and
* semicolon all separate entries. */
var SEPARATOR = /[\s;,]+/;
var input = document.getElementById('atocal-attendees'); var input = document.getElementById('atocal-attendees');
@@ -59,7 +61,7 @@
} }
function commit(email) { function commit(email) {
var parts = input.value.split(/([;,])/); var parts = input.value.split(/([\s;,]+)/);
parts.pop(); parts.pop();
var prefix = parts.join('').replace(/\s+$/, ''); var prefix = parts.join('').replace(/\s+$/, '');
+25
View File
@@ -125,4 +125,29 @@ describe('invitee suggestions', () => {
expect(list.hidden).toBe(true); expect(list.hidden).toBe(true);
expect(list.children).toHaveLength(0); expect(list.children).toHaveLength(0);
}); });
it('searches only the last whitespace-separated fragment', async () => {
fetch.mockReturnValue(response([BOB]));
type('alice@example.com bo');
await settle();
expect(fetch).toHaveBeenCalledWith(
SEARCH_URL + '?query=bo',
expect.objectContaining({ headers: { Accept: 'application/json' } })
);
});
it('keeps whitespace-separated entries when picking a contact', async () => {
fetch.mockReturnValue(response([BOB]));
type('alice@example.com bo');
await settle();
list.querySelector('button').dispatchEvent(
new MouseEvent('mousedown', { bubbles: true, cancelable: true })
);
expect(input.value).toBe('alice@example.com bob@example.com, ');
});
}); });