@@ -18,6 +18,17 @@ @interface Quicksilver_Tests : XCTestCase
1818
1919@implementation Quicksilver_Tests
2020
21+ // / Wait for pending QSGCDAsync + QSGCDMainAsync operations to complete
22+ - (void )waitForAsyncUpdates {
23+ XCTestExpectation *exp = [self expectationWithDescription: @" async updates" ];
24+ dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
25+ dispatch_async (dispatch_get_main_queue (), ^{
26+ [exp fulfill ];
27+ });
28+ });
29+ [self waitForExpectationsWithTimeout: 2.0 handler: nil ];
30+ }
31+
2132
2233- (void )testActionsForURLObject {
2334 NSString *url = @" https://qsapp.com" ;
@@ -202,32 +213,38 @@ - (void)testThirdPaneClosingBehaviour {
202213
203214 // UI tests hack: force the actions timer to fire now
204215 [i fireActionUpdateTimer ];
216+ // Wait for async indirect object updates to complete
217+ [self waitForAsyncUpdates ];
205218 XCTAssertNotNil ([[i aSelector ] objectValue ]);
206-
219+
207220 // the iSelector should be closed
208221 XCTAssertFalse ([self isViewVisible: [i iSelector ] forController: i]);
209-
222+
210223 NSEvent *searchForActionEvent = [NSEvent keyEventWithType: NSEventTypeKeyDown location: NSMakePoint (0 , 0 ) modifierFlags: 256 timestamp: 15127.081604936 windowNumber: [[i window ] windowNumber ] context: nil characters: @" open with" charactersIgnoringModifiers: @" open with" isARepeat: NO keyCode: 0 ];
211224 [[i aSelector ] keyDown: searchForActionEvent];
225+ // Wait for async indirect object updates to complete
226+ [self waitForAsyncUpdates ];
212227 XCTAssertFalse ([[i iSelector ] isHidden ]);
213228 // iSelector should now be visible
214229 XCTAssertTrue ([self isViewVisible: [i iSelector ] forController: i]);
215-
230+
216231 // Clear the first pane (use ⌃U is easiest)
217232 NSEvent *clearEvent = [NSEvent keyEventWithType: NSEventTypeKeyDown location: NSMakePoint (0 , 0 ) modifierFlags: NSEventModifierFlagControl timestamp: 15127.081604936 windowNumber: [[i window ] windowNumber ] context: nil characters: @" u" charactersIgnoringModifiers: @" u" isARepeat: NO keyCode: 32 ];
218233 [[i dSelector ] keyDown: clearEvent];
219234
220235
221236 XCTAssertNil ([[i dSelector ] objectValue ]);
222-
237+
223238 // aSelector still has object until the action timer is fired
224239 XCTAssertNotNil ([[i aSelector ] objectValue ]);
225240 // iSeletor still visible
226241 XCTAssertTrue ([self isViewVisible: [i iSelector ] forController: i]);
227242
228243 // UI tests hack: force the actions timer to fire now
229244 [i fireActionUpdateTimer ];
230-
245+ // Wait for async indirect object updates to complete
246+ [self waitForAsyncUpdates ];
247+
231248 XCTAssertNil ([[i aSelector ] objectValue ]);
232249 // the iSelector should be closed
233250 XCTAssertFalse ([self isViewVisible: [i iSelector ] forController: i]);
0 commit comments