@@ -33,3 +33,83 @@ test('should be reusable after clearing', () => {
3333 readBuffer . append ( Buffer . from ( '\n' ) ) ;
3434 expect ( readBuffer . readMessage ( ) ) . toEqual ( testMessage ) ;
3535} ) ;
36+
37+ describe ( 'non-JSON line filtering' , ( ) => {
38+ test ( 'should skip empty lines' , ( ) => {
39+ const readBuffer = new ReadBuffer ( ) ;
40+ readBuffer . append ( Buffer . from ( '\n\n' + JSON . stringify ( testMessage ) + '\n\n' ) ) ;
41+
42+ expect ( readBuffer . readMessage ( ) ) . toEqual ( testMessage ) ;
43+ expect ( readBuffer . readMessage ( ) ) . toBeNull ( ) ;
44+ } ) ;
45+
46+ test ( 'should skip non-JSON lines before a valid message' , ( ) => {
47+ const readBuffer = new ReadBuffer ( ) ;
48+ readBuffer . append ( Buffer . from ( 'Debug: Starting server\n' + 'Warning: Something happened\n' + JSON . stringify ( testMessage ) + '\n' ) ) ;
49+
50+ expect ( readBuffer . readMessage ( ) ) . toEqual ( testMessage ) ;
51+ expect ( readBuffer . readMessage ( ) ) . toBeNull ( ) ;
52+ } ) ;
53+
54+ test ( 'should skip non-JSON lines interleaved with multiple valid messages' , ( ) => {
55+ const readBuffer = new ReadBuffer ( ) ;
56+ const message1 : JSONRPCMessage = { jsonrpc : '2.0' , method : 'method1' } ;
57+ const message2 : JSONRPCMessage = { jsonrpc : '2.0' , method : 'method2' } ;
58+
59+ readBuffer . append (
60+ Buffer . from (
61+ 'Debug line 1\n' +
62+ JSON . stringify ( message1 ) +
63+ '\n' +
64+ 'Debug line 2\n' +
65+ 'Another non-JSON line\n' +
66+ JSON . stringify ( message2 ) +
67+ '\n'
68+ )
69+ ) ;
70+
71+ expect ( readBuffer . readMessage ( ) ) . toEqual ( message1 ) ;
72+ expect ( readBuffer . readMessage ( ) ) . toEqual ( message2 ) ;
73+ expect ( readBuffer . readMessage ( ) ) . toBeNull ( ) ;
74+ } ) ;
75+
76+ test ( 'should preserve incomplete JSON at end of buffer until completed' , ( ) => {
77+ const readBuffer = new ReadBuffer ( ) ;
78+ readBuffer . append ( Buffer . from ( '{"jsonrpc": "2.0", "method": "test"' ) ) ;
79+ expect ( readBuffer . readMessage ( ) ) . toBeNull ( ) ;
80+
81+ readBuffer . append ( Buffer . from ( '}\n' ) ) ;
82+ expect ( readBuffer . readMessage ( ) ) . toEqual ( { jsonrpc : '2.0' , method : 'test' } ) ;
83+ } ) ;
84+
85+ test ( 'should skip lines with unbalanced braces' , ( ) => {
86+ const readBuffer = new ReadBuffer ( ) ;
87+ readBuffer . append ( Buffer . from ( '{incomplete\n' + 'incomplete}\n' + JSON . stringify ( testMessage ) + '\n' ) ) ;
88+
89+ expect ( readBuffer . readMessage ( ) ) . toEqual ( testMessage ) ;
90+ expect ( readBuffer . readMessage ( ) ) . toBeNull ( ) ;
91+ } ) ;
92+
93+ test ( 'should skip lines that look like JSON but fail to parse' , ( ) => {
94+ const readBuffer = new ReadBuffer ( ) ;
95+ readBuffer . append ( Buffer . from ( '{invalidJson: true}\n' + JSON . stringify ( testMessage ) + '\n' ) ) ;
96+
97+ expect ( readBuffer . readMessage ( ) ) . toEqual ( testMessage ) ;
98+ expect ( readBuffer . readMessage ( ) ) . toBeNull ( ) ;
99+ } ) ;
100+
101+ test ( 'should tolerate leading/trailing whitespace around valid JSON' , ( ) => {
102+ const readBuffer = new ReadBuffer ( ) ;
103+ const message : JSONRPCMessage = { jsonrpc : '2.0' , method : 'test' } ;
104+ readBuffer . append ( Buffer . from ( ' ' + JSON . stringify ( message ) + ' \n' ) ) ;
105+
106+ expect ( readBuffer . readMessage ( ) ) . toEqual ( message ) ;
107+ } ) ;
108+
109+ test ( 'should still throw on valid JSON that fails schema validation' , ( ) => {
110+ const readBuffer = new ReadBuffer ( ) ;
111+ readBuffer . append ( Buffer . from ( '{"not": "a jsonrpc message"}\n' ) ) ;
112+
113+ expect ( ( ) => readBuffer . readMessage ( ) ) . toThrow ( ) ;
114+ } ) ;
115+ } ) ;
0 commit comments