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 4.1 kB View raw
1// src/components/WriteStudio.test.tsx 2import { describe, it, expect, vi, beforeEach } from 'vitest'; 3import { act, createElement } from 'react'; 4import { createRoot } from 'react-dom/client'; 5 6( globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean } ).IS_REACT_ACT_ENVIRONMENT = true; 7 8// Stub the heavy editor: render a marker, ignore props. 9vi.mock( './SkyEditor', () => ( { default: () => createElement( 'div', { 'data-testid': 'sky-editor' } ) } ) ); 10// Stub AppBar to avoid pulling chrome we don't assert on. 11vi.mock( './AppBar', () => ( { default: () => null } ) ); 12 13const auth = vi.hoisted( () => ( { value: {} as Record< string, unknown > } ) ); 14vi.mock( '../lib/auth/AuthProvider', () => ( { 15 AuthProvider: ( { children }: { children: unknown } ) => children, 16} ) ); 17vi.mock( '../lib/auth/useAuth', () => ( { useAuth: () => auth.value } ) ); 18 19const draft = vi.hoisted( () => ( { 20 store: { 21 load: vi.fn( async () => null ), 22 save: vi.fn( async () => {} ), 23 clear: vi.fn( async () => {} ), 24 setPublishIntent: vi.fn(), 25 consumePublishIntent: vi.fn( () => false ), 26 }, 27} ) ); 28vi.mock( '../lib/write/draft-store', () => ( { 29 createDraftStore: () => draft.store, 30} ) ); 31vi.mock( '../lib/publish/publications', () => ( { 32 listPublications: vi.fn( async () => [] ), 33} ) ); 34 35import WriteStudio from './WriteStudio'; 36 37function render() { 38 const container = document.createElement( 'div' ); 39 document.body.appendChild( container ); 40 const root = createRoot( container ); 41 return { container, root }; 42} 43 44beforeEach( () => { 45 draft.store.consumePublishIntent.mockReturnValue( false ); 46 draft.store.load.mockResolvedValue( null ); 47} ); 48 49describe( 'WriteStudio', () => { 50 it( 'signed out: no gate — renders the editor and a Publish action, with no sign-in shown until Publish is hit', async () => { 51 auth.value = { status: 'signed-out', agent: null, did: null, handle: null, signIn: vi.fn(), signOut: vi.fn() }; 52 const { container, root } = render(); 53 await act( async () => { 54 root.render( createElement( WriteStudio ) ); 55 } ); 56 // The editor is always present (no login gate)… 57 expect( container.querySelector( '[data-testid="sky-editor"]' ) ).not.toBe( null ); 58 // …and the only auth-adjacent affordance is Publish — no persistent "Sign in" button, 59 // and no sign-in panel until the writer hits Publish. 60 expect( container.querySelector( '.write-publish' ) ).not.toBe( null ); 61 expect( container.querySelector( '.signin-panel' ) ).toBe( null ); 62 expect( container.textContent?.toLowerCase() ).not.toContain( 'sign in' ); 63 } ); 64 65 it( 'signed in: renders the editor and the Publish action, and does NOT duplicate the identity pill (the app bar carries it)', async () => { 66 auth.value = { 67 status: 'signed-in', agent: {}, did: 'did:plc:me', handle: 'me.test', 68 displayName: 'Me', avatar: null, pdsUrl: 'https://pds', signIn: vi.fn(), signOut: vi.fn(), 69 }; 70 const { container, root } = render(); 71 await act( async () => { 72 root.render( createElement( WriteStudio ) ); 73 } ); 74 expect( container.querySelector( '[data-testid="sky-editor"]' ) ).not.toBe( null ); 75 expect( container.querySelector( '.write-publish' ) ).not.toBe( null ); 76 // The app bar (mocked out here) is the single source of the signed-in identity — 77 // WriteStudio must not render its own duplicate pill. 78 expect( container.querySelector( '.account-pill' ) ).toBe( null ); 79 } ); 80 81 it( 'resume: a publish intent on a signed-in load opens the publish flow', async () => { 82 draft.store.consumePublishIntent.mockReturnValue( true ); 83 auth.value = { 84 status: 'signed-in', agent: {}, did: 'did:plc:me', handle: 'me.test', 85 displayName: 'Me', avatar: null, pdsUrl: 'https://pds', signIn: vi.fn(), signOut: vi.fn(), 86 }; 87 const { container, root } = render(); 88 await act( async () => { 89 root.render( createElement( WriteStudio ) ); 90 } ); 91 expect( container.querySelector( '.writeflow' ) ).not.toBe( null ); 92 // The top Publish action gives way to the stepper — no redundant button. 93 expect( container.querySelector( '.write-actions' ) ).toBe( null ); 94 } ); 95} );