@@ -372,6 +372,126 @@ class ChatChannelListViewModel_Tests: StreamChatTestCase {
372372 XCTAssertNotNil ( viewModel. messageSearchController)
373373 }
374374
375+ // MARK: - Open Channel
376+
377+ func test_openChannel_whenChannelExistsInList_shouldScrollToAndOpenChannel( ) {
378+ // Given
379+ let channel = ChatChannel . mockDMChannel ( )
380+ let channelListController = makeChannelListController ( channels: [ channel] )
381+ let viewModel = ChatChannelListViewModel (
382+ channelListController: channelListController,
383+ selectedChannelId: nil
384+ )
385+
386+ // When
387+ viewModel. openChannel ( with: channel. cid)
388+
389+ // Then
390+ XCTAssertEqual ( viewModel. scrolledChannelId, channel. id)
391+
392+ // Wait for the async delay and verify selectedChannel is set
393+ let expectation = XCTestExpectation ( description: " Channel opened " )
394+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.4 ) {
395+ XCTAssertEqual ( viewModel. selectedChannel? . channel. id, channel. id)
396+ XCTAssertNil ( viewModel. scrolledChannelId)
397+ expectation. fulfill ( )
398+ }
399+ wait ( for: [ expectation] , timeout: 1.0 )
400+ }
401+
402+ func test_openChannel_whenChannelNotInList_shouldLoadNextChannelsUntilFound( ) {
403+ // Given
404+ let existingChannel = ChatChannel . mockDMChannel ( )
405+ let targetChannel = ChatChannel . mockDMChannel ( )
406+ let channelListController = makeChannelListController ( channels: [ existingChannel] )
407+ let viewModel = ChatChannelListViewModel (
408+ channelListController: channelListController,
409+ selectedChannelId: nil
410+ )
411+
412+ // When
413+ viewModel. openChannel ( with: targetChannel. cid)
414+
415+ // Then
416+ XCTAssertEqual ( channelListController. loadNextChannelsCallCount, 1 )
417+
418+ // Simulate the channel being found after loading
419+ channelListController. simulate (
420+ channels: [ existingChannel, targetChannel] ,
421+ changes: [ . insert( targetChannel, index: . init( row: 1 , section: 0 ) ) ]
422+ )
423+
424+ // When
425+ viewModel. openChannel ( with: targetChannel. cid)
426+
427+ // Verify the channel is eventually opened
428+ let expectation = XCTestExpectation ( description: " Channel opened after loading " )
429+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.3 ) {
430+ XCTAssertEqual ( viewModel. selectedChannel? . channel. id, targetChannel. id)
431+ XCTAssertNil ( viewModel. scrolledChannelId)
432+ expectation. fulfill ( )
433+ }
434+ wait ( for: [ expectation] , timeout: 1.0 )
435+ }
436+
437+ func test_openChannel_whenChannelNotFoundAndNoMoreChannels_shouldSetScrolledChannelIdToNil( ) {
438+ // Given
439+ let existingChannel = ChatChannel . mockDMChannel ( )
440+ let targetChannel = ChatChannel . mockDMChannel ( )
441+ let channelListController = makeChannelListController ( channels: [ existingChannel] )
442+ let viewModel = ChatChannelListViewModel (
443+ channelListController: channelListController,
444+ selectedChannelId: nil
445+ )
446+
447+ // When
448+ viewModel. openChannel ( with: targetChannel. cid)
449+
450+ // Then
451+ XCTAssertNil ( viewModel. scrolledChannelId)
452+ XCTAssertNil ( viewModel. selectedChannel)
453+ }
454+
455+ func test_openChannel_whenChannelFoundAfterMultipleLoads_shouldEventuallyOpenChannel( ) {
456+ // Given
457+ let existingChannel = ChatChannel . mockDMChannel ( )
458+ let targetChannel = ChatChannel . mockDMChannel ( )
459+ let channelListController = makeChannelListController ( channels: [ existingChannel] )
460+ let viewModel = ChatChannelListViewModel (
461+ channelListController: channelListController,
462+ selectedChannelId: nil
463+ )
464+
465+ // When
466+ viewModel. openChannel ( with: targetChannel. cid)
467+
468+ // Then
469+ XCTAssertEqual ( channelListController. loadNextChannelsCallCount, 1 )
470+
471+ // Simulate first load not finding the channel
472+ channelListController. simulate (
473+ channels: [ existingChannel] ,
474+ changes: [ ]
475+ )
476+
477+ // Simulate second load finding the channel
478+ channelListController. simulate (
479+ channels: [ existingChannel, targetChannel] ,
480+ changes: [ . insert( targetChannel, index: . init( row: 1 , section: 0 ) ) ]
481+ )
482+
483+ viewModel. openChannel ( with: targetChannel. cid)
484+
485+ // Verify the channel is eventually opened
486+ let expectation = XCTestExpectation ( description: " Channel opened after multiple loads " )
487+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.3 ) {
488+ XCTAssertEqual ( viewModel. selectedChannel? . channel. id, targetChannel. id)
489+ XCTAssertNil ( viewModel. scrolledChannelId)
490+ expectation. fulfill ( )
491+ }
492+ wait ( for: [ expectation] , timeout: 1.0 )
493+ }
494+
375495 // MARK: - private
376496
377497 private func makeChannelListController(
0 commit comments