@@ -13,6 +13,10 @@ import LanguageServerProtocol
13
13
14
14
@testable import CodeEdit
15
15
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.
16
20
final class LanguageServerCodeFileDocumentTests : XCTestCase {
17
21
// Test opening documents in CodeEdit triggers creating a language server,
18
22
// further opened documents don't create new servers
@@ -97,8 +101,11 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
97
101
// This is usually sent from the LSPService
98
102
try await server. openDocument ( codeFile)
99
103
100
- await waitForClientEventCount (
101
- 3 ,
104
+ await waitForClientState (
105
+ (
106
+ [ . initialize] ,
107
+ [ . initialized, . textDocumentDidOpen]
108
+ ) ,
102
109
connection: connection,
103
110
description: " Initialized (2) and opened (1) notification count "
104
111
)
@@ -110,22 +117,27 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
110
117
return codeFile
111
118
}
112
119
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 {
114
125
let expectation = expectation ( description: description)
115
126
116
127
await withTaskGroup ( of: Void . self) { group in
128
+ group. addTask { await self . fulfillment ( of: [ expectation] , timeout: 2 ) }
117
129
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 {
122
132
expectation. fulfill ( )
123
133
return
124
134
}
125
135
}
126
136
}
127
137
}
128
138
139
+ // MARK: - Open Close
140
+
129
141
@MainActor
130
142
func testOpenCloseFileNotifications( ) async throws {
131
143
// Set up test server
@@ -155,40 +167,38 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
155
167
file. fileDocument = codeFile
156
168
CodeEditDocumentController . shared. addDocument ( codeFile)
157
169
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
+ )
159
178
160
179
// This should then trigger a documentDidClose event
161
180
codeFile. close ( )
162
181
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 "
179
189
)
180
190
}
181
191
192
+ // MARK: - Test Document Edit
193
+
182
194
/// Assert the changed contents received by the buffered connection
183
195
func assertExpectedContentChanges( connection: BufferingServerConnection , changes: [ String ] ) {
184
196
var foundChangeContents : [ String ] = [ ]
185
197
186
198
for notification in connection. clientNotifications {
187
199
switch notification {
188
200
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) )
192
202
default :
193
203
continue
194
204
}
@@ -233,18 +243,17 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
233
243
textView. replaceCharacters ( in: NSRange ( location: 39 , length: 0 ) , with: " World " )
234
244
235
245
// 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
+ )
237
254
238
255
// Make sure our text view is intact
239
256
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
- )
248
257
249
258
// Expect only one change due to throttling.
250
259
assertExpectedContentChanges (
@@ -291,18 +300,17 @@ final class LanguageServerCodeFileDocumentTests: XCTestCase {
291
300
textView. replaceCharacters ( in: NSRange ( location: 39 , length: 0 ) , with: " World " )
292
301
293
302
// 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
+ )
295
311
296
312
// Make sure our text view is intact
297
313
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
- )
306
314
307
315
// Expect three content changes.
308
316
assertExpectedContentChanges (
0 commit comments