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 3.2 kB View raw
1/** 2 * Source-level guard for the Open Graph wiring in Base.astro. 3 * 4 * Rendering the layout through astro/container is not viable in this suite (the 5 * runner is pinned to jsdom for the WordPress block tests — see 6 * src/pages/index.phase.test.ts). So, like that test, we pin the wiring at the 7 * source level: Base must compute absolute URLs, call buildMetaTags, render the 8 * tags, and emit a canonical link. The tag *shapes* are unit-tested in 9 * src/lib/seo/meta.test.ts. 10 */ 11import { readFileSync } from 'node:fs'; 12import { dirname, join } from 'node:path'; 13import { fileURLToPath } from 'node:url'; 14import { describe, expect, it } from 'vitest'; 15 16const here = dirname( fileURLToPath( import.meta.url ) ); 17const read = ( rel: string ) => readFileSync( join( here, rel ), 'utf8' ); 18 19describe( 'Base.astro Open Graph wiring', () => { 20 const base = read( './Base.astro' ); 21 22 it( 'imports the buildMetaTags helper', () => { 23 expect( base ).toMatch( /import\s*\{\s*buildMetaTags\s*\}\s*from\s*'\.\.\/lib\/seo\/meta'/ ); 24 } ); 25 26 it( 'derives an absolute canonical URL and image URL from Astro.site', () => { 27 expect( base ).toMatch( /new URL\(\s*Astro\.url\.pathname,\s*Astro\.site\s*\)/ ); 28 expect( base ).toMatch( /new URL\(\s*image,\s*Astro\.site\s*\)/ ); 29 } ); 30 31 it( 'renders the built meta tags into <head>', () => { 32 expect( base ).toMatch( /metaTags\.map/ ); 33 expect( base ).toMatch( /<meta\s+property=\{/ ); 34 expect( base ).toMatch( /<meta\s+name=\{/ ); 35 } ); 36 37 it( 'emits a canonical link', () => { 38 expect( base ).toMatch( /<link\s+rel="canonical"/ ); 39 } ); 40 41 it( 'defaults the share image to the shared og-default.png', () => { 42 expect( base ).toMatch( /\/og-default\.png/ ); 43 } ); 44 45 it( 'guards the canonical link + social tags behind an opt-out socialMeta prop', () => { 46 // Defaults on, so callers that pass nothing are unaffected. 47 expect( base ).toMatch( /socialMeta\s*=\s*true/ ); 48 // The canonical + meta block only renders when socialMeta is truthy, so 49 // pages that manage their own head tags (e.g. articles) can opt out. 50 expect( base ).toMatch( /socialMeta\s*&&/ ); 51 } ); 52 53 it( 'accepts optional imageWidth/imageHeight props', () => { 54 expect( base ).toMatch( /imageWidth\??:\s*number/ ); 55 expect( base ).toMatch( /imageHeight\??:\s*number/ ); 56 } ); 57 58 it( 'only defaults the 1200x630 dimensions for the built-in default image', () => { 59 // A flag distinguishes the default image from a caller-supplied one. 60 expect( base ).toMatch( /og-default\.png/ ); 61 // The 1200x630 defaults must be gated behind the isDefaultImage guard, so 62 // caller-supplied images don't silently inherit the default dimensions. 63 expect( base ).toMatch( /isDefaultImage\s*\?\s*1200/ ); 64 expect( base ).toMatch( /isDefaultImage\s*\?\s*630/ ); 65 // Dimensions are threaded into buildMetaTags. 66 expect( base ).toMatch( /imageWidth:/ ); 67 expect( base ).toMatch( /imageHeight:/ ); 68 } ); 69} ); 70 71describe( 'article page metadata', () => { 72 const article = read( '../pages/[author]/[slug]/[rkey].astro' ); 73 74 it( 'opts out of Base social meta so its own OG + canonical tags are not duplicated', () => { 75 expect( article ).toMatch( /<Base[^>]*\ssocialMeta=\{\s*false\s*\}/s ); 76 } ); 77} );