@@ -1907,50 +1907,53 @@ describe("App <-> AppBridge integration", () => {
19071907 describe ( "pre-handshake guard (claude-ai-mcp#149)" , ( ) => {
19081908 const guardMsg =
19091909 / c a l l e d b e f o r e c o n n e c t \( \) c o m p l e t e d t h e u i \/ i n i t i a l i z e h a n d s h a k e / ;
1910+ let warnSpy : ReturnType < typeof spyOn < Console , "warn" > > ;
1911+
1912+ beforeEach ( ( ) => {
1913+ warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
1914+ } ) ;
1915+ afterEach ( ( ) => {
1916+ warnSpy . mockRestore ( ) ;
1917+ } ) ;
1918+
1919+ const warnings = ( ) => warnSpy . mock . calls . map ( ( c ) => String ( c [ 0 ] ) ) ;
19101920
19111921 it ( "callServerTool warns when called before connect() completes" , async ( ) => {
1912- const errSpy = spyOn ( console , "error" ) . mockImplementation ( ( ) => { } ) ;
19131922 bridge . oncalltool = async ( ) => ( { content : [ ] } ) ;
19141923 await bridge . connect ( bridgeTransport ) ;
19151924
19161925 const connecting = app . connect ( appTransport ) ;
19171926 // Handshake is in flight; _initializedSent is still false.
19181927 await app . callServerTool ( { name : "t" , arguments : { } } ) . catch ( ( ) => { } ) ;
19191928
1920- expect ( errSpy ) . toHaveBeenCalledTimes ( 1 ) ;
1921- expect ( errSpy . mock . calls [ 0 ] [ 0 ] ) . toMatch ( guardMsg ) ;
1922- expect ( errSpy . mock . calls [ 0 ] [ 0 ] ) . toContain ( "App.callServerTool()" ) ;
1929+ const appSide = warnings ( ) . filter ( ( m ) => guardMsg . test ( m ) ) ;
1930+ expect ( appSide ) . toHaveLength ( 1 ) ;
1931+ expect ( appSide [ 0 ] ) . toContain ( "App.callServerTool()" ) ;
19231932
19241933 await connecting ;
1925- errSpy . mockRestore ( ) ;
19261934 } ) ;
19271935
19281936 it ( "callServerTool does not warn after connect() resolves" , async ( ) => {
1929- const errSpy = spyOn ( console , "error" ) . mockImplementation ( ( ) => { } ) ;
19301937 bridge . oncalltool = async ( ) => ( { content : [ ] } ) ;
19311938 await bridge . connect ( bridgeTransport ) ;
19321939 await app . connect ( appTransport ) ;
19331940
19341941 await app . callServerTool ( { name : "t" , arguments : { } } ) ;
19351942
1936- expect ( errSpy ) . not . toHaveBeenCalled ( ) ;
1937- errSpy . mockRestore ( ) ;
1943+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
19381944 } ) ;
19391945
19401946 it ( "sendMessage and readServerResource also warn before handshake" , async ( ) => {
1941- const errSpy = spyOn ( console , "error" ) . mockImplementation ( ( ) => { } ) ;
1942-
19431947 await app . sendMessage ( { role : "user" , content : [ ] } ) . catch ( ( ) => { } ) ;
19441948 await app . readServerResource ( { uri : "test://r" } ) . catch ( ( ) => { } ) ;
19451949
1946- expect ( errSpy ) . toHaveBeenCalledTimes ( 2 ) ;
1947- expect ( errSpy . mock . calls [ 0 ] [ 0 ] ) . toContain ( "App.sendMessage()" ) ;
1948- expect ( errSpy . mock . calls [ 1 ] [ 0 ] ) . toContain ( "App.readServerResource ()" ) ;
1949- errSpy . mockRestore ( ) ;
1950+ const appSide = warnings ( ) . filter ( ( m ) => guardMsg . test ( m ) ) ;
1951+ expect ( appSide ) . toHaveLength ( 2 ) ;
1952+ expect ( appSide [ 0 ] ) . toContain ( "App.sendMessage ()" ) ;
1953+ expect ( appSide [ 1 ] ) . toContain ( "App.readServerResource()" ) ;
19501954 } ) ;
19511955
19521956 it ( "throws instead of warning when strict: true" , async ( ) => {
1953- const errSpy = spyOn ( console , "error" ) . mockImplementation ( ( ) => { } ) ;
19541957 const strictApp = new App (
19551958 testAppInfo ,
19561959 { } ,
@@ -1960,78 +1963,65 @@ describe("App <-> AppBridge integration", () => {
19601963 await expect (
19611964 strictApp . callServerTool ( { name : "t" , arguments : { } } ) ,
19621965 ) . rejects . toThrow ( guardMsg ) ;
1963- expect ( errSpy ) . not . toHaveBeenCalled ( ) ;
1964-
1965- errSpy . mockRestore ( ) ;
1966+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
19661967 } ) ;
19671968
19681969 describe ( "late handler registration" , ( ) => {
19691970 const lateMsg =
19701971 / h a n d l e r r e g i s t e r e d a f t e r c o n n e c t \( \) c o m p l e t e d t h e u i \/ i n i t i a l i z e h a n d s h a k e / ;
19711972
19721973 it ( "warns when ontoolresult is set after connect() resolves" , async ( ) => {
1973- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
19741974 await bridge . connect ( bridgeTransport ) ;
19751975 await app . connect ( appTransport ) ;
19761976
19771977 app . ontoolresult = ( ) => { } ;
19781978
1979- expect ( warnSpy ) . toHaveBeenCalledTimes ( 1 ) ;
1980- expect ( warnSpy . mock . calls [ 0 ] [ 0 ] ) . toMatch ( lateMsg ) ;
1981- expect ( warnSpy . mock . calls [ 0 ] [ 0 ] ) . toContain ( '"toolresult"' ) ;
1982- warnSpy . mockRestore ( ) ;
1979+ expect ( warnings ( ) ) . toHaveLength ( 1 ) ;
1980+ expect ( warnings ( ) [ 0 ] ) . toMatch ( lateMsg ) ;
1981+ expect ( warnings ( ) [ 0 ] ) . toContain ( '"toolresult"' ) ;
19831982 } ) ;
19841983
19851984 it ( "warns when addEventListener('toolinput', …) is called after connect()" , async ( ) => {
1986- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
19871985 await bridge . connect ( bridgeTransport ) ;
19881986 await app . connect ( appTransport ) ;
19891987
19901988 app . addEventListener ( "toolinput" , ( ) => { } ) ;
19911989
1992- expect ( warnSpy ) . toHaveBeenCalledTimes ( 1 ) ;
1993- expect ( warnSpy . mock . calls [ 0 ] [ 0 ] ) . toContain ( '"toolinput"' ) ;
1994- warnSpy . mockRestore ( ) ;
1990+ expect ( warnings ( ) ) . toHaveLength ( 1 ) ;
1991+ expect ( warnings ( ) [ 0 ] ) . toContain ( '"toolinput"' ) ;
19951992 } ) ;
19961993
19971994 it ( "does not warn for handlers set before connect()" , async ( ) => {
1998- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
19991995 app . ontoolinput = ( ) => { } ;
20001996 app . addEventListener ( "toolresult" , ( ) => { } ) ;
20011997
20021998 await bridge . connect ( bridgeTransport ) ;
20031999 await app . connect ( appTransport ) ;
20042000
2005- expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
2006- warnSpy . mockRestore ( ) ;
2001+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
20072002 } ) ;
20082003
20092004 it ( "does not warn for hostcontextchanged (repeating event)" , async ( ) => {
2010- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
20112005 await bridge . connect ( bridgeTransport ) ;
20122006 await app . connect ( appTransport ) ;
20132007
20142008 app . onhostcontextchanged = ( ) => { } ;
20152009 app . addEventListener ( "hostcontextchanged" , ( ) => { } ) ;
20162010
2017- expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
2018- warnSpy . mockRestore ( ) ;
2011+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
20192012 } ) ;
20202013
20212014 it ( "does not warn when clearing a handler (set to undefined)" , async ( ) => {
2022- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
20232015 app . ontoolinput = ( ) => { } ;
20242016 await bridge . connect ( bridgeTransport ) ;
20252017 await app . connect ( appTransport ) ;
20262018
20272019 app . ontoolinput = undefined ;
20282020
2029- expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
2030- warnSpy . mockRestore ( ) ;
2021+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
20312022 } ) ;
20322023
20332024 it ( "throws instead of warning when strict: true" , async ( ) => {
2034- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
20352025 const [ strictAppT , strictBridgeT ] =
20362026 InMemoryTransport . createLinkedPair ( ) ;
20372027 const strictBridge = new AppBridge (
@@ -2053,13 +2043,11 @@ describe("App <-> AppBridge integration", () => {
20532043 expect ( ( ) => {
20542044 strictApp . addEventListener ( "toolinput" , ( ) => { } ) ;
20552045 } ) . toThrow ( lateMsg ) ;
2056- expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
2057- warnSpy . mockRestore ( ) ;
2046+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
20582047 } ) ;
20592048 } ) ;
20602049
20612050 it ( "AppBridge warns on tools/call from a View that skipped the handshake" , async ( ) => {
2062- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
20632051 bridge . oncalltool = async ( ) => ( { content : [ ] } ) ;
20642052 await bridge . connect ( bridgeTransport ) ;
20652053
@@ -2073,23 +2061,20 @@ describe("App <-> AppBridge integration", () => {
20732061 } ) ;
20742062 await flush ( ) ;
20752063
2076- expect ( warnSpy ) . toHaveBeenCalledTimes ( 1 ) ;
2077- expect ( warnSpy . mock . calls [ 0 ] [ 0 ] ) . toContain (
2064+ expect ( warnings ( ) ) . toHaveLength ( 1 ) ;
2065+ expect ( warnings ( ) [ 0 ] ) . toContain (
20782066 "received 'tools/call' before ui/notifications/initialized" ,
20792067 ) ;
2080- warnSpy . mockRestore ( ) ;
20812068 } ) ;
20822069
20832070 it ( "AppBridge does not warn after initialized is received" , async ( ) => {
2084- const warnSpy = spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
20852071 bridge . oncalltool = async ( ) => ( { content : [ ] } ) ;
20862072 await bridge . connect ( bridgeTransport ) ;
20872073 await app . connect ( appTransport ) ;
20882074
20892075 await app . callServerTool ( { name : "t" , arguments : { } } ) ;
20902076
2091- expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
2092- warnSpy . mockRestore ( ) ;
2077+ expect ( warnings ( ) ) . toEqual ( [ ] ) ;
20932078 } ) ;
20942079 } ) ;
20952080
0 commit comments