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.2 kB View raw
1/** 2 * Source-level guards for the landing redesign (spec 2026-06-09). The .astro pages 3 * can't render through the jsdom-pinned vitest, so we assert on source — same approach 4 * as src/pages/index.phase.test.ts. 5 */ 6import { existsSync, readFileSync } from 'node:fs'; 7import { fileURLToPath } from 'node:url'; 8import { describe, expect, it } from 'vitest'; 9 10// Resolve at module scope: jsdom swaps the global `URL` for one based at 11// http://localhost, so `new URL( rel, import.meta.url )` only stays a file:// 12// URL when it runs at collection time (module/describe-body evaluation, before 13// jsdom takes over) rather than inside an `it()` callback. 14const resolve = ( rel: string ) => fileURLToPath( new URL( rel, import.meta.url ) ); 15const read = ( rel: string ) => readFileSync( resolve( rel ), 'utf8' ); 16 17describe( 'site footer links', () => { 18 const footer = read( '../../components/Footer.astro' ); 19 20 it( 'links the lexicon under a Docs label', () => { 21 expect( footer ).toMatch( /href=["']\/lexicon["'][^>]*>[\s\S]*?Docs/ ); 22 } ); 23 24 it( 'links the SkyPress launch article under a News label', () => { 25 expect( footer ).toMatch( 26 /href=["']https:\/\/skypress\.blog\/@skypress\.blog\/its-always-sunny-on-skypress["'][^>]*>[\s\S]*?News/ 27 ); 28 } ); 29 30 it( 'links the SkyPress source repo on tangled.org with an accessible label and icon', () => { 31 expect( footer ).toMatch( 32 /href=["']https:\/\/tangled\.org\/jeremy\.herve\.bzh\/skypress["'][\s\S]*?aria-label=[\s\S]*?<svg/ 33 ); 34 } ); 35} ); 36 37describe( 'sample/preview page is retired', () => { 38 const previewRoute = resolve( '../../pages/preview.astro' ); 39 40 it( 'no longer ships the /preview route', () => { 41 expect( existsSync( previewRoute ) ).toBe( false ); 42 } ); 43 44 it( 'is not linked from the landing or lexicon pages', () => { 45 expect( read( '../../pages/index.astro' ) ).not.toMatch( /\/preview/ ); 46 expect( read( '../../pages/lexicon.astro' ) ).not.toMatch( /\/preview/ ); 47 } ); 48} ); 49 50describe( 'landing hero redesign', () => { 51 const index = read( '../../pages/index.astro' ); 52 53 it( 'leads with a single "Start writing" CTA to /write and no on-page sign-in', () => { 54 // Writing-first: the hero's only action starts a draft on /write. The handle sign-in 55 // island was removed — signing in happens via Publish on /write, not from the home page. 56 expect( index ).toMatch( /href="\/write"[^>]*>\s*Start writing/ ); 57 expect( index ).not.toMatch( /HandleStart/ ); 58 } ); 59 60 it( 'drops the old sample / lexicon / studio hero buttons', () => { 61 expect( index ).not.toMatch( /Read a sample/ ); 62 expect( index ).not.toMatch( /See the lexicon/ ); 63 expect( index ).not.toMatch( /href="\/editor">Studio/ ); 64 } ); 65 66 it( 'states that SkyPress is free', () => { 67 expect( index ).toMatch( /[Ff]ree/ ); 68 } ); 69 70 it( 'no longer carries the Bluesky cross-post note on the home page', () => { 71 // The "One thing worth knowing…" notice was removed from the landing page 72 // (commit c1508f9); the cross-post disclosure now lives on the publish panel. 73 expect( index ).not.toMatch( /posts to Bluesky/ ); 74 } ); 75 76 it( 'shows the three-up "see it in action" screenshot strip', () => { 77 expect( index ).toMatch( /\/screenshots\/editor\.png/ ); 78 expect( index ).toMatch( /\/screenshots\/published-article\.png/ ); 79 expect( index ).toMatch( /\/screenshots\/author-page\.png/ ); 80 } ); 81 82 it( 'no longer renders the three-step how-it-works list', () => { 83 expect( index ).not.toMatch( /class="steps"/ ); 84 } ); 85} ); 86 87describe( 'playful: shooting star', () => { 88 const index = read( '../../pages/index.astro' ); 89 90 it( 'renders a shooting-star element inside the decorative sky', () => { 91 expect( index ).toMatch( /class="shootingstar"/ ); 92 } ); 93 94 it( 'animates only in dark phases', () => { 95 const style = index.match( /<style>([\s\S]*?)<\/style>/ )?.[ 1 ] ?? ''; 96 expect( style ).toMatch( /:global\(\s*\[data-phase='night'\]\s*\)\s*\.shootingstar/ ); 97 } ); 98 99 it( 'is silenced under reduced motion', () => { 100 const style = index.match( /<style>([\s\S]*?)<\/style>/ )?.[ 1 ] ?? ''; 101 const reduced = style.match( /@media \(prefers-reduced-motion: reduce\) \{([\s\S]*?)\}/ )?.[ 1 ] ?? ''; 102 expect( reduced ).toMatch( /\.shootingstar/ ); 103 } ); 104} );