11import { beforeEach , describe , expect , it , jest } from "bun:test"
22import {
33 BmClient ,
4- isProjectAlreadyExistsError ,
54 isMissingEditNoteCommandError ,
65 isNoteNotFoundError ,
6+ isProjectAlreadyExistsError ,
77 isUnsupportedStripFrontmatterError ,
88 parseJsonOutput ,
99 stripFrontmatter ,
@@ -47,18 +47,18 @@ Warning: something happened
4747 new Error ( "No such option: --strip-frontmatter" ) ,
4848 ) ,
4949 ) . toBe ( true )
50- expect ( isUnsupportedStripFrontmatterError ( new Error ( "different error" ) ) ) . toBe (
51- false ,
52- )
50+ expect (
51+ isUnsupportedStripFrontmatterError ( new Error ( "different error" ) ) ,
52+ ) . toBe ( false )
5353 } )
5454
5555 it ( "detects missing edit-note command errors" , ( ) => {
5656 expect (
5757 isMissingEditNoteCommandError ( new Error ( "No such command 'edit-note'" ) ) ,
5858 ) . toBe ( true )
59- expect ( isMissingEditNoteCommandError ( new Error ( "validation failed" ) ) ) . toBe (
60- false ,
61- )
59+ expect (
60+ isMissingEditNoteCommandError ( new Error ( "validation failed" ) ) ,
61+ ) . toBe ( false )
6262 } )
6363
6464 it ( "detects note-not-found errors and excludes missing command errors" , ( ) => {
@@ -199,9 +199,7 @@ describe("BmClient behavior", () => {
199199 } )
200200
201201 it ( "ensureProject throws when project creation fails for other reasons" , async ( ) => {
202- const execRaw = jest
203- . fn ( )
204- . mockRejectedValue ( new Error ( "permission denied" ) )
202+ const execRaw = jest . fn ( ) . mockRejectedValue ( new Error ( "permission denied" ) )
205203 ; ( client as any ) . execRaw = execRaw
206204
207205 await expect ( client . ensureProject ( "/tmp/memory" ) ) . rejects . toThrow (
@@ -230,13 +228,49 @@ describe("BmClient behavior", () => {
230228 ] )
231229 } )
232230
231+ it ( "listProjects runs bm project list --format json" , async ( ) => {
232+ const execRaw = jest . fn ( ) . mockResolvedValue (
233+ JSON . stringify ( [
234+ {
235+ name : "alpha" ,
236+ path : "/tmp/alpha" ,
237+ display_name : "Alpha Project" ,
238+ is_private : true ,
239+ is_default : true ,
240+ } ,
241+ ] ) ,
242+ )
243+ ; ( client as any ) . execRaw = execRaw
244+
245+ const projects = await client . listProjects ( )
246+
247+ expect ( execRaw ) . toHaveBeenCalledWith ( [
248+ "project" ,
249+ "list" ,
250+ "--format" ,
251+ "json" ,
252+ ] )
253+ expect ( projects ) . toEqual ( [
254+ {
255+ name : "alpha" ,
256+ path : "/tmp/alpha" ,
257+ display_name : "Alpha Project" ,
258+ is_private : true ,
259+ is_default : true ,
260+ } ,
261+ ] )
262+ } )
263+
233264 it ( "indexConversation does not create fallback note on non-not-found edit errors" , async ( ) => {
234265 ; ( client as any ) . editNote = jest
235266 . fn ( )
236267 . mockRejectedValue ( new Error ( "No such command 'edit-note'" ) )
237268 ; ( client as any ) . writeNote = jest . fn ( )
238269
239- await client . indexConversation ( "user message long enough" , "assistant reply long enough" )
270+ await client . indexConversation (
271+ "user message long enough" ,
272+ "assistant reply long enough" ,
273+ )
240274
241275 expect ( ( client as any ) . writeNote ) . not . toHaveBeenCalled ( )
242276 } )
@@ -252,7 +286,10 @@ describe("BmClient behavior", () => {
252286 file_path : "conversations/x.md" ,
253287 } )
254288
255- await client . indexConversation ( "user message long enough" , "assistant reply long enough" )
289+ await client . indexConversation (
290+ "user message long enough" ,
291+ "assistant reply long enough" ,
292+ )
256293
257294 expect ( ( client as any ) . writeNote ) . toHaveBeenCalledTimes ( 1 )
258295 const [ title , content , folder ] = ( client as any ) . writeNote . mock . calls [ 0 ]
0 commit comments