hotkeyTargets.test.ts2.7 KBView on GitHub /**
* Which driver a keyboard target goes to.
*
* The failure this guards is silent and destructive-looking: `x`, `u`, `i`, `h` and `#` all
* resolve one target set, and handing a chat row to the Gmail driver issues a modify for a
* thread id Gmail never had. The lookup alone cannot decide it — selection and hover state
* outlive a feed replacement, so "the feed does not know this id" happens in normal use.
*/
import { splitHotkeyTargets, isChannelSelectionId } from '@/modules/inbox/lib/hotkey-targets';
import type { InboxItem } from '@/modules/inbox/types';
const item = (id: string, channel: InboxItem['channel']): InboxItem =>
({ id, channel }) as InboxItem;
/** A feed holding one email row and one LinkedIn row. */
const feed = new Map<string, InboxItem>([
['18ab2f9c1d', item('18ab2f9c1d', 'email')],
['li:chat-1', item('li:chat-1', 'linkedin')],
]);
const lookup = (id: string) => feed.get(id);
describe('splitHotkeyTargets', () => {
it('sends a resolved email row to the email half', () => {
expect(splitHotkeyTargets(['18ab2f9c1d'], lookup)).toMatchObject({
emailIds: ['18ab2f9c1d'],
channelItems: [],
});
});
it('sends a resolved chat row to the channel half', () => {
const out = splitHotkeyTargets(['li:chat-1'], lookup);
expect(out.emailIds).toEqual([]);
expect(out.channelItems.map((i) => i.id)).toEqual(['li:chat-1']);
});
it.each(['li:gone', 'wa:gone', 'slack:ws:chan'])(
'never hands an unresolved %s to Gmail',
(id) => {
// The row left the loaded feed but the selection survived. Dropping it is the only
// safe answer: there is no item to act on, and Gmail has no such thread.
expect(splitHotkeyTargets([id], lookup)).toMatchObject({
ids: [id],
emailIds: [],
channelItems: [],
});
},
);
it('still treats an unresolved BARE id as email', () => {
// The non-unibox case: nothing is in the feed and every id is a Gmail thread id.
expect(splitHotkeyTargets(['18ab2f9c1d', 'ffee00'], () => undefined)).toMatchObject({
emailIds: ['18ab2f9c1d', 'ffee00'],
channelItems: [],
});
});
it('keeps `ids` as the full set in list order, whatever each one turned out to be', () => {
const out = splitHotkeyTargets(['18ab2f9c1d', 'li:gone', 'li:chat-1'], lookup);
expect(out.ids).toEqual(['18ab2f9c1d', 'li:gone', 'li:chat-1']);
});
});
describe('isChannelSelectionId', () => {
it.each(['li:chat-1', 'wa:chat-2', 'slack:ws:chan:1700.1'])('is true for %s', (id) => {
expect(isChannelSelectionId(id)).toBe(true);
});
it.each(['18ab2f9c1d', 'ffee00', 'lithium', 'wander'])('is false for %s', (id) => {
expect(isChannelSelectionId(id)).toBe(false);
});
});