Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  ChatViewSnapshotProviderTests.swift   Sprache: JAVA

 

import Combine
import Foundation
import ThreemaEssentials
import XCTest
@testable import Threema
@testable import ThreemaFramework

final class ChatViewSnapshotProviderTests: XCTestCase {
    private var testDatabase: TestDatabase!

    private var internalInitialSetupCompleted = false
    
    override func setUp() {
        super.setUp()
        
        AppGroup.setGroupID("group.ch.threema") // THREEMA_GROUP_IDENTIFIER @"group.ch.threema"
        
        testDatabase = TestDatabase()
    }
    
    override func tearDown() {
        super.tearDown()
    }
    
    func testBasicSetup() {
        let entityManager = testDatabase.entityManager

        let conversation = createContactAndConversation(
            entityManager: entityManager,
            identity: "ECHOECHO"
        ).conversation
        
        createMessage(in: conversation, entityManager: entityManager)
        
        XCTAssertEqual(MessageFetcher(for: conversation, with: entityManager).count(), 1)
        
        let messageProvider = MessageProvider(
            for: conversation,
            around: nil,
            entityManager: entityManager,
            backgroundEntityManager: entityManager,
            context: testDatabase.context.current
        )
        
        let snapshotProvider = ChatViewSnapshotProvider(
            conversation: conversation,
            entityManager: entityManager,
            messageProvider: messageProvider,
            unreadMessagesSnapshot: UnreadMessagesStateManager(
                conversation: conversation,
                businessInjector: BusinessInjectorMock(entityManager: entityManager),
                notificationManager: NotificationManagerMock(),
                unreadMessagesStateManagerDelegate: UnreadMessagesStateManagerDelegateMock()
            ),
            delegate: self,
            userSettings: UserSettingsMock()
        )
        
        let expectation = expectation(description: "Single Snapshot")
        expectation.expectedFulfillmentCount = 1
        expectation.assertForOverFulfill = true
        
        var cancellables = Set<AnyCancellable>()
        
        snapshotProvider.$snapshotInfo
            .receive(on: DispatchQueue.global())
            .sink { snapshot in
                guard let diffableDataSourceSnapshot = snapshot?.snapshot else {
                    return
                }
            
                XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                XCTAssertEqual(diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count, 0)

                XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 1)
            
                expectation.fulfill()
            }.store(in: &cancellables)
        
        guard MessageFetcher(for: conversation, with: entityManager).lastDisplayMessage() != nil else {
            fatalError()
        }
        
        waitForExpectations(timeout: 10)
    }
    
    func testBasicPublish() {
        let entityManager = testDatabase.entityManager

        let conversation = createContactAndConversation(
            entityManager: entityManager,
            identity: "ECHOECHO"
        ).conversation
        
        createMessage(in: conversation, entityManager: entityManager)
        
        XCTAssertEqual(MessageFetcher(for: conversation, with: entityManager).count(), 1)
        
        let messageProvider = MessageProvider(
            for: conversation,
            around: nil,
            entityManager: entityManager,
            backgroundEntityManager: entityManager,
            context: testDatabase.context.current
        )
        
        let snapshotProvider = ChatViewSnapshotProvider(
            conversation: conversation,
            entityManager: entityManager,
            messageProvider: messageProvider,
            unreadMessagesSnapshot: UnreadMessagesStateManager(
                conversation: conversation,
                businessInjector: BusinessInjectorMock(entityManager: entityManager),
                notificationManager: NotificationManagerMock(),
                unreadMessagesStateManagerDelegate: UnreadMessagesStateManagerDelegateMock()
            ),
            delegate: self,
            userSettings: UserSettingsMock()
        )
        
        var cancellables = Set<AnyCancellable>()
        
        typealias Check = (
            check: (ChatViewSnapshotProvider.ChatViewDiffableDataSourceSnapshot) -> Void,
            postcheck: () -> Void
        )
        
        let checks: [Check] = [
            (
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    XCTAssertEqual(diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count, 0)

                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 1)
                },
                {
                    DispatchQueue.global().async {
                        self.createMessage(in: conversation, entityManager: entityManager)
                    }
                }
            ),
            (
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        2
                    )

                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 2)
                },
                { }
            ),
        ]
        
        let expectation = expectation(description: "Single Snapshot")
        expectation.expectedFulfillmentCount = checks.count
        expectation.assertForOverFulfill = true
        
        var i = 0
        snapshotProvider.$snapshotInfo
            .receive(on: DispatchQueue.global())
            .sink { snapshot in
                guard let diffableDataSourceSnapshot = snapshot?.snapshot else {
                    return
                }
            
                checks[i].check(diffableDataSourceSnapshot)
            
                checks[i].postcheck()
            
                i += 1
            
                expectation.fulfill()
            }.store(in: &cancellables)
        
        waitForExpectations(timeout: 10)
    }
        
    func testBasicAddUnreadMessageLine() {
        basicUnreadMessageLine()
    }
    
    func basicUnreadMessageLine() {
        let entityManager = testDatabase.entityManager

        let conversation = createContactAndConversation(
            entityManager: entityManager,
            identity: "ECHOECHO"
        ).conversation
        
        createMessage(in: conversation, entityManager: entityManager)
        
        XCTAssertEqual(MessageFetcher(for: conversation, with: entityManager).count(), 1)
        
        let messageProvider = MessageProvider(
            for: conversation,
            around: nil,
            entityManager: entityManager,
            backgroundEntityManager: entityManager,
            context: testDatabase.context.current
        )
        
        let typingIndicatorInformationProvider = ChatViewTypingIndicatorInformationProviderMock()
        let userSettingsMock = UserSettingsMock()
        
        let snapshotProvider = ChatViewSnapshotProvider(
            conversation: conversation,
            entityManager: entityManager,
            messageProvider: messageProvider,
            unreadMessagesSnapshot: UnreadMessagesStateManager(
                conversation: conversation,
                businessInjector: BusinessInjectorMock(entityManager: entityManager),
                notificationManager: NotificationManagerMock(),
                unreadMessagesStateManagerDelegate: UnreadMessagesStateManagerDelegateMock()
            ),
            typingIndicatorInformationProvider: typingIndicatorInformationProvider,
            delegate: self,
            userSettings: userSettingsMock
        )
        
        var cancellables = Set<AnyCancellable>()
        
        typealias Check = (
            check: (ChatViewSnapshotProvider.ChatViewDiffableDataSourceSnapshot) -> Void,
            postcheck: () -> Void
        )
        
        let checks: [Check] = [
            (
                // Check 0
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    XCTAssertEqual(diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count, 0)
                    
                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 1)
                },
                {
                    DispatchQueue.global().async {
                        self.createMessage(in: conversation, entityManager: entityManager)
                    }
                }
            ),
            (
                // Check 1
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        2
                    )

                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 2)
                },
                {
                    self.internalInitialSetupCompleted = true
                    typingIndicatorInformationProvider.currentlyTyping = true
                }
            ),
            (
                // Check 2
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        2
                    )

                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 3)
                    
                    XCTAssert(diffableDataSourceSnapshot.itemIdentifiers.contains(.typingIndicator))
                    
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.itemIdentifiers.last,
                        .typingIndicator
                    )
                },
                { }
            ),
        ]
        
        let expectation = expectation(description: "Single Snapshot")
        expectation.expectedFulfillmentCount = checks.count
        expectation.assertForOverFulfill = true
        
        var i = 0
        snapshotProvider.$snapshotInfo
            .receive(on: DispatchQueue.global())
            .sink { snapshot in
                guard let diffableDataSourceSnapshot = snapshot?.snapshot else {
                    return
                }
            
                checks[i].check(diffableDataSourceSnapshot)
            
                checks[i].postcheck()
            
                print("Executed check \(i)")
                
                i += 1
            
                expectation.fulfill()
            }.store(in: &cancellables)
        
        waitForExpectations(timeout: 10)
    }
    
    // TODO: (IOS-3875) Timeout
    func testUnreadMessageLineStillLastAfterNewMessageSent() {
        let entityManager = testDatabase.entityManager

        let conversation = createContactAndConversation(
            entityManager: entityManager,
            identity: "ECHOECHO"
        ).conversation
        
        createMessage(in: conversation, entityManager: entityManager)
        
        XCTAssertEqual(MessageFetcher(for: conversation, with: entityManager).count(), 1)
        
        let messageProvider = MessageProvider(
            for: conversation,
            around: nil,
            entityManager: entityManager,
            backgroundEntityManager: entityManager,
            context: testDatabase.context.current
        )
        
        let typingIndicatorInformationProvider = ChatViewTypingIndicatorInformationProviderMock()
        let userSettingsMock = UserSettingsMock()
        
        let snapshotProvider = ChatViewSnapshotProvider(
            conversation: conversation,
            entityManager: entityManager,
            messageProvider: messageProvider,
            unreadMessagesSnapshot: UnreadMessagesStateManager(
                conversation: conversation,
                businessInjector: BusinessInjectorMock(entityManager: entityManager),
                notificationManager: NotificationManagerMock(),
                unreadMessagesStateManagerDelegate: UnreadMessagesStateManagerDelegateMock()
            ),
            typingIndicatorInformationProvider: typingIndicatorInformationProvider,
            delegate: self,
            userSettings: userSettingsMock
        )
        
        var cancellables = Set<AnyCancellable>()
        
        typealias Check = (
            check: (ChatViewSnapshotProvider.ChatViewDiffableDataSourceSnapshot) -> Void,
            postcheck: () -> Void
        )
        
        let checks: [Check] = [
            (
                // Check 0
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    XCTAssertEqual(diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count, 0)
                    
                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 1)
                },
                {
                    DispatchQueue.global().async {
                        self.createMessage(in: conversation, entityManager: entityManager)
                    }
                }
            ),
            (
                // Check 1
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        2
                    )

                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 2)
                },
                {
                    entityManager.performAndWaitSave {
                        conversation.typing = true
                        self.internalInitialSetupCompleted = true
                        typingIndicatorInformationProvider.currentlyTyping = true
                    }
                }
            ),
            (
                // Check 2
                { diffableDataSourceSnapshot in
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                   
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        2
                    )

                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 3)
                    
                    XCTAssert(diffableDataSourceSnapshot.itemIdentifiers.contains(.typingIndicator))
                    
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.last, .typingIndicator)
                },
                {
                    DispatchQueue.global().async {
                        self.createMessage(in: conversation, entityManager: entityManager)
                    }
                }
            ),
            (
                // Check 3
                { diffableDataSourceSnapshot in
                    // Correct number of reloads
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        3
                    )

                    // Correct number of items
                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 4)
                    
                    // Correct State for Unread Message line
                    XCTAssert(diffableDataSourceSnapshot.itemIdentifiers.contains(.typingIndicator))
                    
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.last, .typingIndicator)
                },
                {
                    entityManager.performAndWaitSave {
                        typingIndicatorInformationProvider.currentlyTyping = false
                        conversation.typing = false
                    }
                }
            ),
            (
                // Check 4
                { diffableDataSourceSnapshot in
                    // Correct number of reloads
                    XCTAssertEqual(diffableDataSourceSnapshot.reloadedItemIdentifiers.count, 0)
                    
                    // Starting with iOS 18 updating `lastMessage` on `Conversation` leads to the previous last
                    // message to be marked as reloaded (even tough there is no reverse relationship) and after our
                    // processing to a reconfigured item and neighboring items. This actually fixes some neighboring
                    // update issues
                    XCTAssertEqual(
                        diffableDataSourceSnapshot.reconfiguredItemIdentifiers.count,
                        3
                    )

                    // Correct number of items
                    XCTAssertEqual(diffableDataSourceSnapshot.numberOfSections, 1)
                    XCTAssertEqual(diffableDataSourceSnapshot.itemIdentifiers.count, 3)
                    
                    // Correct State for Unread Message line
                    XCTAssertFalse(diffableDataSourceSnapshot.itemIdentifiers.contains(.typingIndicator))
                },
                { }
            ),
        ]
        
        let expectation = expectation(description: "Single Snapshot")
        expectation.expectedFulfillmentCount = checks.count
        expectation.assertForOverFulfill = true
        
        var i = 0
        snapshotProvider.$snapshotInfo
            .receive(on: DispatchQueue.global())
            .sink { snapshot in
                guard let diffableDataSourceSnapshot = snapshot?.snapshot else {
                    return
                }
            
                checks[i].check(diffableDataSourceSnapshot)
            
                checks[i].postcheck()
            
                print("Executed check \(i)")
                
                i += 1
            
                expectation.fulfill()
            }.store(in: &cancellables)
        
        // TODO: (IOS-3875) Timeout
        waitForExpectations(timeout: 100)
    }
    
    private func createMessage(in conversation: ConversationEntity, entityManager: EntityManager) {
        _ = entityManager.performAndWaitSave {
            entityManager.entityCreator.textMessageEntity(text: "Hello World", in: conversation, setLastUpdate: true)
        }
    }
    
    private func createContactAndConversation(entityManager: EntityManager, identity: String)
        -> (contact: ContactEntity, conversation: ConversationEntity) {
        var contact: ContactEntity!
        
        entityManager.performAndWaitSave {
            contact = entityManager.entityCreator.contactEntity(
                identity: identity,
                publicKey: BytesUtility.generateRandomBytes(length: Int(32))!,
                sortOrderFirstName: true
            )
            contact.contactVerificationLevel = .unverified
            contact.publicNickname = identity
            contact.isHidden = false
            contact.workContact = 0
        }
        
        let conversation = entityManager.conversation(
            forContact: contact,
            createIfNotExisting: true
        )!
            
        assert(contact.identity == identity)
        
        return (contact, conversation)
    }
}

// MARK: - ChatViewSnapshotProviderDelegate

extension ChatViewSnapshotProviderTests: ChatViewSnapshotProviderDelegate {
    var initialSetupCompleted: Bool {
        internalInitialSetupCompleted
    }
    
    var unreadMessagesInfo: (totalUnreadMessagesCount: Int, newestUnreadMessage: NSManagedObjectID?)? {
        nil
    }
    
    var nextSnapshotShouldShowUnreadMessageLine: Bool? {
        false
    }
    
    var previousUnreadMessage: NSManagedObjectID? {
        nil
    }
    
    var deletedMessagesObjectIDs: Set<NSManagedObjectID> {
        Set()
    }
}

Messung
CHZG
86889890

¤ Dauer der Verarbeitung: 0.11 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104838
#Domains=499078