1- import { describe , it , expect , vi } from "vitest" ;
1+ import { describe , it , expect } from "vitest" ;
22import { readFileSync } from "fs" ;
33import { dirname , relative , resolve } from "path" ;
44import { fileURLToPath } from "url" ;
5+ import type { Session } from "./types.js" ;
56
67const __dirname = dirname ( fileURLToPath ( import . meta. url ) ) ;
78const REPO_ROOT = resolve ( __dirname , "../../.." ) ;
89
10+ function createTestSession ( ) : Session & { messages : string [ ] } {
11+ const messages : string [ ] = [ ] ;
12+ return {
13+ messages,
14+ log : {
15+ debug : ( ...args : unknown [ ] ) => messages . push ( String ( args . join ( " " ) ) ) ,
16+ info : ( ...args : unknown [ ] ) => messages . push ( String ( args . join ( " " ) ) ) ,
17+ warn : ( ...args : unknown [ ] ) => messages . push ( String ( args . join ( " " ) ) ) ,
18+ error : ( ...args : unknown [ ] ) => messages . push ( String ( args . join ( " " ) ) ) ,
19+ } ,
20+ } ;
21+ }
22+
923const lexiconFiles = {
1024 facet : {
1125 id : "pub.oxa.richtext.facet" ,
@@ -154,7 +168,7 @@ function documentNode(
154168 } satisfies TestDocumentNode ;
155169}
156170
157- async function flatten ( inlines : unknown [ ] ) {
171+ async function flatten ( inlines : unknown [ ] , session ?: Session ) {
158172 const convertModule = await import ( "./convert.js" ) . catch ( ( error ) => {
159173 if ( error instanceof Error && error . message . includes ( "/src/convert.js" ) ) {
160174 return undefined ;
@@ -170,10 +184,10 @@ async function flatten(inlines: unknown[]) {
170184 "Expected packages/oxa-core/src/convert.ts to export flattenInlines" ,
171185 ) . toBeTypeOf ( "function" ) ;
172186
173- return flattenInlines ! ( inlines as never ) ;
187+ return flattenInlines ! ( session ?? createTestSession ( ) , inlines as never ) ;
174188}
175189
176- async function map ( block : unknown ) {
190+ async function map ( block : unknown , session ?: Session ) {
177191 const convertModule = await import ( "./convert.js" ) ;
178192 const mapBlock = convertModule . mapBlock ;
179193
@@ -182,10 +196,14 @@ async function map(block: unknown) {
182196 "Expected packages/oxa-core/src/convert.ts to export mapBlock" ,
183197 ) . toBeTypeOf ( "function" ) ;
184198
185- return mapBlock ! ( block as never ) ;
199+ return mapBlock ! ( session ?? createTestSession ( ) , block as never ) ;
186200}
187201
188- async function convertDocument ( document : unknown , options ?: unknown ) {
202+ async function convertDocument (
203+ document : unknown ,
204+ options ?: unknown ,
205+ session ?: Session ,
206+ ) {
189207 const convertModule = await import ( "./convert.js" ) ;
190208 const oxaToAtproto = convertModule . oxaToAtproto ;
191209
@@ -194,7 +212,11 @@ async function convertDocument(document: unknown, options?: unknown) {
194212 "Expected packages/oxa-core/src/convert.ts to export oxaToAtproto" ,
195213 ) . toBeTypeOf ( "function" ) ;
196214
197- return oxaToAtproto ! ( document as never , options as never ) ;
215+ return oxaToAtproto ! (
216+ session ?? createTestSession ( ) ,
217+ document as never ,
218+ options as never ,
219+ ) ;
198220}
199221
200222function readLexicon ( filePath : string ) : LexiconDoc {
@@ -208,12 +230,6 @@ function readLexicon(filePath: string): LexiconDoc {
208230 }
209231}
210232
211- function stderrOutput ( writeSpy : ReturnType < typeof vi . spyOn > ) {
212- return writeSpy . mock . calls
213- . map ( ( [ chunk ] : [ unknown , ...unknown [ ] ] ) => String ( chunk ) )
214- . join ( "" ) ;
215- }
216-
217233// eslint-disable-next-line @typescript-eslint/no-explicit-any
218234function getLexiconDefs ( filePath : string ) : Record < string , any > {
219235 // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -402,29 +418,25 @@ describe("mapBlock", () => {
402418 } ) ;
403419
404420 it ( "warns and omits unknown block types instead of coercing them into known ATProto blocks" , async ( ) => {
405- const writeSpy = vi
406- . spyOn ( process . stderr , "write" )
407- . mockImplementation ( ( ) => true ) ;
421+ const session = createTestSession ( ) ;
408422
409- try {
410- await expect (
411- map ( {
412- type : "Callout" ,
413- children : [ text ( "Should be dropped" ) ] ,
414- id : "callout-1" ,
415- classes : [ "note" ] ,
416- data : { severity : "warning" } ,
417- } ) ,
418- ) . resolves . toBeUndefined ( ) ;
423+ const result = await map (
424+ {
425+ type : "Callout" ,
426+ children : [ text ( "Should be dropped" ) ] ,
427+ id : "callout-1" ,
428+ classes : [ "note" ] ,
429+ data : { severity : "warning" } ,
430+ } ,
431+ session ,
432+ ) ;
419433
420- expect ( writeSpy ) . toHaveBeenCalled ( ) ;
434+ expect ( result ) . toBeUndefined ( ) ;
435+ expect ( session . messages . length ) . toBeGreaterThan ( 0 ) ;
421436
422- const warning = stderrOutput ( writeSpy ) ;
423- expect ( warning ) . toContain ( "unknown block type" ) ;
424- expect ( warning ) . toContain ( "Callout" ) ;
425- } finally {
426- writeSpy . mockRestore ( ) ;
427- }
437+ const warning = session . messages . join ( "\n" ) ;
438+ expect ( warning ) . toContain ( "unknown block type" ) ;
439+ expect ( warning ) . toContain ( "Callout" ) ;
428440 } ) ;
429441} ) ;
430442
@@ -507,50 +519,45 @@ describe("oxaToAtproto", () => {
507519 tags : [ "oxa" , "atproto" ] ,
508520 } ,
509521 } ;
510- const writeSpy = vi
511- . spyOn ( process . stderr , "write" )
512- . mockImplementation ( ( ) => true ) ;
513-
514- try {
515- const converted = await convertDocument (
516- {
517- type : "Document" ,
518- metadata,
519- children : [
520- paragraph ( [ text ( "Keep this paragraph" ) ] ) ,
521- {
522- type : "Callout" ,
523- children : [ text ( "Drop this block" ) ] ,
524- data : { severity : "warning" } ,
525- } ,
526- ] ,
527- } ,
528- { createdAt } ,
529- ) ;
522+ const session = createTestSession ( ) ;
530523
531- expect ( converted ) . toEqual ( {
532- $type : "pub.oxa.document.document" ,
524+ const converted = await convertDocument (
525+ {
526+ type : "Document" ,
533527 metadata,
534528 children : [
529+ paragraph ( [ text ( "Keep this paragraph" ) ] ) ,
535530 {
536- $ type : "pub.oxa.document.defs#paragraph " ,
537- text : "Keep this paragraph" ,
538- facets : [ ] ,
531+ type : "Callout " ,
532+ children : [ text ( "Drop this block" ) ] ,
533+ data : { severity : "warning" } ,
539534 } ,
540535 ] ,
541- createdAt,
542- } ) ;
543- expect ( converted . metadata ) . toBe ( metadata ) ;
544- expect ( "title" in converted ) . toBe ( false ) ;
536+ } ,
537+ { createdAt } ,
538+ session ,
539+ ) ;
540+
541+ expect ( converted ) . toEqual ( {
542+ $type : "pub.oxa.document.document" ,
543+ metadata,
544+ children : [
545+ {
546+ $type : "pub.oxa.document.defs#paragraph" ,
547+ text : "Keep this paragraph" ,
548+ facets : [ ] ,
549+ } ,
550+ ] ,
551+ createdAt,
552+ } ) ;
553+ expect ( converted . metadata ) . toBe ( metadata ) ;
554+ expect ( "title" in converted ) . toBe ( false ) ;
545555
546- expect ( writeSpy ) . toHaveBeenCalled ( ) ;
556+ expect ( session . messages . length ) . toBeGreaterThan ( 0 ) ;
547557
548- const warning = stderrOutput ( writeSpy ) ;
549- expect ( warning ) . toContain ( "unknown block type" ) ;
550- expect ( warning ) . toContain ( "Callout" ) ;
551- } finally {
552- writeSpy . mockRestore ( ) ;
553- }
558+ const warning = session . messages . join ( "\n" ) ;
559+ expect ( warning ) . toContain ( "unknown block type" ) ;
560+ expect ( warning ) . toContain ( "Callout" ) ;
554561 } ) ;
555562} ) ;
556563
@@ -769,39 +776,36 @@ describe("flattenInlines", () => {
769776 ) ;
770777 } ) ;
771778
772- it ( "warns to stderr and drops inline id, classes, and data properties on formatting nodes" , async ( ) => {
773- const writeSpy = vi
774- . spyOn ( process . stderr , "write" )
775- . mockImplementation ( ( ) => true ) ;
779+ it ( "warns and drops inline id, classes, and data properties on formatting nodes" , async ( ) => {
780+ const session = createTestSession ( ) ;
776781
777- try {
778- const richText = await flatten ( [
782+ const richText = await flatten (
783+ [
779784 strong ( [ text ( "styled" ) ] , {
780785 id : "inline-id" ,
781786 classes : [ "callout" , "accent" ] ,
782787 data : { note : "keep warning only" } ,
783788 } ) ,
784- ] ) ;
789+ ] ,
790+ session ,
791+ ) ;
785792
786- expect ( richText ) . toEqual ( {
787- text : "styled" ,
788- facets : [
789- {
790- index : { byteStart : 0 , byteEnd : 6 } ,
791- features : [ { $type : "pub.oxa.richtext.facet#strong" } ] ,
792- } ,
793- ] ,
794- } ) ;
793+ expect ( richText ) . toEqual ( {
794+ text : "styled" ,
795+ facets : [
796+ {
797+ index : { byteStart : 0 , byteEnd : 6 } ,
798+ features : [ { $type : "pub.oxa.richtext.facet#strong" } ] ,
799+ } ,
800+ ] ,
801+ } ) ;
795802
796- expect ( writeSpy ) . toHaveBeenCalled ( ) ;
803+ expect ( session . messages . length ) . toBeGreaterThan ( 0 ) ;
797804
798- const warning = stderrOutput ( writeSpy ) ;
799- expect ( warning ) . toContain ( "Strong" ) ;
800- expect ( warning ) . toContain ( "id" ) ;
801- expect ( warning ) . toContain ( "classes" ) ;
802- expect ( warning ) . toContain ( "data" ) ;
803- } finally {
804- writeSpy . mockRestore ( ) ;
805- }
805+ const warning = session . messages . join ( "\n" ) ;
806+ expect ( warning ) . toContain ( "Strong" ) ;
807+ expect ( warning ) . toContain ( "id" ) ;
808+ expect ( warning ) . toContain ( "classes" ) ;
809+ expect ( warning ) . toContain ( "data" ) ;
806810 } ) ;
807811} ) ;
0 commit comments