A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1import { describe, it, expect, vi } from 'vitest';
2import type { Agent } from '@atproto/api';
3import { uploadHeldAssets } from './upload-held';
4import type { BlockNode } from '../blocks/render';
5
6const DATA = 'data:image/png;base64,QUFB'; // "AAA"
7
8function fakeAgent() {
9 const uploadBlob = vi.fn( async ( _file: Blob ) => ( {
10 data: { blob: { ref: { toString: () => 'bafyCID' }, mimeType: 'image/png', size: 3 } },
11 } ) );
12 return { agent: { uploadBlob } as unknown as Agent, uploadBlob };
13}
14
15describe( 'uploadHeldAssets', () => {
16 it( 'uploads each held image, attaches skypressBlob + a getBlob url, leaves externals alone', async () => {
17 const { agent, uploadBlob } = fakeAgent();
18 const blocks: BlockNode[] = [
19 { name: 'core/image', attributes: { url: DATA }, innerBlocks: [] },
20 { name: 'core/image', attributes: { url: 'https://ext/x.png' }, innerBlocks: [] },
21 ];
22
23 const out = await uploadHeldAssets( agent, {
24 blocks,
25 coverDataUrl: null,
26 did: 'did:plc:me',
27 pdsUrl: 'https://pds.example.com',
28 } );
29
30 expect( uploadBlob ).toHaveBeenCalledTimes( 1 );
31 expect( out.blocks[ 0 ].attributes!.skypressBlob ).toEqual( {
32 $type: 'blob',
33 ref: { $link: 'bafyCID' },
34 mimeType: 'image/png',
35 size: 3,
36 } );
37 expect( out.blocks[ 0 ].attributes!.url ).toBe(
38 'https://pds.example.com/xrpc/com.atproto.sync.getBlob?did=did%3Aplc%3Ame&cid=bafyCID'
39 );
40 expect( out.blocks[ 1 ].attributes!.url ).toBe( 'https://ext/x.png' );
41 expect( out.coverImage ).toBeUndefined();
42 } );
43
44 it( 'uploads a held cover into a BlobRefJson', async () => {
45 const { agent } = fakeAgent();
46 const out = await uploadHeldAssets( agent, {
47 blocks: [],
48 coverDataUrl: DATA,
49 did: 'did:plc:me',
50 pdsUrl: 'https://pds.example.com',
51 } );
52 expect( out.coverImage ).toEqual( {
53 $type: 'blob',
54 ref: { $link: 'bafyCID' },
55 mimeType: 'image/png',
56 size: 3,
57 } );
58 } );
59} );