A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

at trunk 2.9 kB View raw
1import { describe, expect, it, vi } from 'vitest'; 2import { renderToString } from 'react-dom/server'; 3import { 4 createMentionCompleter, 5 replaceAtMentionCompleter, 6} from './mention-autocompleter'; 7import type { ActorPreview } from '../landing/actor-lookup'; 8 9const ALICE: ActorPreview = { 10 did: 'did:plc:alice', 11 handle: 'alice.bsky.social', 12 displayName: 'Alice', 13 avatar: null, 14}; 15 16const ALICIA: ActorPreview = { 17 did: 'did:plc:alicia', 18 handle: 'alicia.blog', 19 displayName: 'Alicia', 20 avatar: null, 21}; 22 23describe( 'mention autocompleter', () => { 24 it( 'has an @ trigger prefix', () => { 25 const completer = createMentionCompleter( async () => [] ); 26 expect( completer.triggerPrefix ).toBe( '@' ); 27 } ); 28 29 it( 'returns the typeahead search results as options for a partial query', async () => { 30 const search = vi.fn( async () => [ ALICE, ALICIA ] ); 31 const completer = createMentionCompleter( search ); 32 const options = await completer.options( 'ali' ); 33 expect( options ).toEqual( [ ALICE, ALICIA ] ); 34 expect( search ).toHaveBeenCalledWith( 'ali' ); 35 } ); 36 37 it( 'returns no options for an empty query without searching', async () => { 38 const search = vi.fn( async () => [ ALICE ] ); 39 const completer = createMentionCompleter( search ); 40 expect( await completer.options( '' ) ).toEqual( [] ); 41 expect( await completer.options( ' ' ) ).toEqual( [] ); 42 expect( search ).not.toHaveBeenCalled(); 43 } ); 44 45 it( 'completes to a mention anchor element (inserted at the caret, not block-replacing)', () => { 46 const completer = createMentionCompleter( async () => [] ); 47 // The completion is the anchor element itself, so the editor inserts it inline in 48 // place of the typed `@query` rather than swapping out the whole block. 49 const completion = completer.getOptionCompletion( ALICE ); 50 const html = renderToString( completion ); 51 expect( html ).toContain( 'href="https://mu.social/profile/alice.bsky.social"' ); 52 expect( html ).toContain( 'data-did="did:plc:alice"' ); 53 expect( html ).toContain( '@alice.bsky.social' ); 54 } ); 55} ); 56 57describe( 'replaceAtMentionCompleter', () => { 58 const mention = createMentionCompleter( async () => [] ); 59 60 it( "drops WordPress's built-in @ user completer and appends ours", () => { 61 const builtInUser = { name: 'user', triggerPrefix: '@' }; 62 const blockCompleter = { name: 'block', triggerPrefix: '/' }; 63 const result = replaceAtMentionCompleter( 64 [ builtInUser, blockCompleter ], 65 mention 66 ); 67 // The '/' completer survives; the '@' user completer is gone; ours is last. 68 expect( result ).toEqual( [ blockCompleter, mention ] ); 69 } ); 70 71 it( 'returns only our completer when the base set is empty or not an array', () => { 72 expect( replaceAtMentionCompleter( [], mention ) ).toEqual( [ mention ] ); 73 expect( replaceAtMentionCompleter( undefined, mention ) ).toEqual( [ mention ] ); 74 } ); 75} );