@@ -13,6 +13,10 @@ import LanguageServerProtocol
1313
1414@testable import CodeEdit
1515
16+ /// This is an integration test for notifications relating to the ``CodeFileDocument`` class.
17+ ///
18+ /// For *unit* tests with the language server class, add tests to the `LanguageServer+DocumentObjects` test class as
19+ /// it's cleaner and makes correct use of the mock document type.
1620final class LanguageServerCodeFileDocumentTests : XCTestCase {
1721 // Test opening documents in CodeEdit triggers creating a language server,
1822 // further opened documents don't create new servers
@@ -97,8 +101,11 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
97101 // This is usually sent from the LSPService
98102 try await server. openDocument ( codeFile)
99103
100- await waitForClientEventCount (
101- 3 ,
104+ await waitForClientState (
105+ (
106+ [ . initialize] ,
107+ [ . initialized, . textDocumentDidOpen]
108+ ) ,
102109 connection: connection,
103110 description: " Initialized (2) and opened (1) notification count "
104111 )
@@ -110,22 +117,27 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
110117 return codeFile
111118 }
112119
113- func waitForClientEventCount( _ count: Int , connection: BufferingServerConnection , description: String ) async {
120+ func waitForClientState(
121+ _ expectedValue: ( [ ClientRequest . Method ] , [ ClientNotification . Method ] ) ,
122+ connection: BufferingServerConnection ,
123+ description: String
124+ ) async {
114125 let expectation = expectation ( description: description)
115126
116127 await withTaskGroup ( of: Void . self) { group in
128+ group. addTask { await self . fulfillment ( of: [ expectation] , timeout: 2 ) }
117129 group. addTask {
118- await self . fulfillment ( of: [ expectation] , timeout: 2 )
119- }
120- group. addTask {
121- for await events in connection. clientEventSequence where events. 0 . count + events. 1 . count == count {
130+ for await events in connection. clientEventSequence
131+ where events. 0 . map ( \. method) == expectedValue. 0 && events. 1 . map ( \. method) == expectedValue. 1 {
122132 expectation. fulfill ( )
123133 return
124134 }
125135 }
126136 }
127137 }
128138
139+ // MARK: - Open Close
140+
129141 @MainActor
130142 func testOpenCloseFileNotifications( ) async throws {
131143 // Set up test server
@@ -155,40 +167,38 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
155167 file. fileDocument = codeFile
156168 CodeEditDocumentController . shared. addDocument ( codeFile)
157169
158- await waitForClientEventCount ( 3 , connection: connection, description: " Pre-close event count " )
170+ await waitForClientState (
171+ (
172+ [ . initialize] ,
173+ [ . initialized, . textDocumentDidOpen]
174+ ) ,
175+ connection: connection,
176+ description: " Pre-close event count "
177+ )
159178
160179 // This should then trigger a documentDidClose event
161180 codeFile. close ( )
162181
163- await waitForClientEventCount ( 4 , connection: connection, description: " Post-close event count " )
164-
165- XCTAssertEqual (
166- connection. clientRequests. map { $0. method } ,
167- [
168- ClientRequest . Method. initialize,
169- ]
170- )
171-
172- XCTAssertEqual (
173- connection. clientNotifications. map { $0. method } ,
174- [
175- ClientNotification . Method. initialized,
176- ClientNotification . Method. textDocumentDidOpen,
177- ClientNotification . Method. textDocumentDidClose
178- ]
182+ await waitForClientState (
183+ (
184+ [ . initialize] ,
185+ [ . initialized, . textDocumentDidOpen, . textDocumentDidClose]
186+ ) ,
187+ connection: connection,
188+ description: " Post-close event count "
179189 )
180190 }
181191
192+ // MARK: - Test Document Edit
193+
182194 /// Assert the changed contents received by the buffered connection
183195 func assertExpectedContentChanges( connection: BufferingServerConnection , changes: [ String ] ) {
184196 var foundChangeContents : [ String ] = [ ]
185197
186198 for notification in connection. clientNotifications {
187199 switch notification {
188200 case let . textDocumentDidChange( params) :
189- foundChangeContents. append ( contentsOf: params. contentChanges. map { event in
190- event. text
191- } )
201+ foundChangeContents. append ( contentsOf: params. contentChanges. map ( \. text) )
192202 default :
193203 continue
194204 }
@@ -233,18 +243,17 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
233243 textView. replaceCharacters ( in: NSRange ( location: 39 , length: 0 ) , with: " World " )
234244
235245 // Added one notification
236- await waitForClientEventCount ( 4 , connection: connection, description: " Edited notification count " )
246+ await waitForClientState (
247+ (
248+ [ . initialize] ,
249+ [ . initialized, . textDocumentDidOpen, . textDocumentDidChange]
250+ ) ,
251+ connection: connection,
252+ description: " Edited notification count "
253+ )
237254
238255 // Make sure our text view is intact
239256 XCTAssertEqual ( textView. string, #"func testFunction() -> String { "Hello World" }"# )
240- XCTAssertEqual (
241- [
242- ClientNotification . Method. initialized,
243- ClientNotification . Method. textDocumentDidOpen,
244- ClientNotification . Method. textDocumentDidChange
245- ] ,
246- connection. clientNotifications. map { $0. method }
247- )
248257
249258 // Expect only one change due to throttling.
250259 assertExpectedContentChanges (
@@ -291,18 +300,17 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
291300 textView. replaceCharacters ( in: NSRange ( location: 39 , length: 0 ) , with: " World " )
292301
293302 // Throttling means we should receive one edited notification + init notification + didOpen + init request
294- await waitForClientEventCount ( 4 , connection: connection, description: " Edited notification count " )
303+ await waitForClientState (
304+ (
305+ [ . initialize] ,
306+ [ . initialized, . textDocumentDidOpen, . textDocumentDidChange]
307+ ) ,
308+ connection: connection,
309+ description: " Edited notification count "
310+ )
295311
296312 // Make sure our text view is intact
297313 XCTAssertEqual ( textView. string, #"func testFunction() -> String { "Hello World" }"# )
298- XCTAssertEqual (
299- [
300- ClientNotification . Method. initialized,
301- ClientNotification . Method. textDocumentDidOpen,
302- ClientNotification . Method. textDocumentDidChange
303- ] ,
304- connection. clientNotifications. map { $0. method }
305- )
306314
307315 // Expect three content changes.
308316 assertExpectedContentChanges (
0 commit comments