mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			396 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			396 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Swift
		
	
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | 
						|
 | 
						|
import Combine
 | 
						|
import GRDB
 | 
						|
import Quick
 | 
						|
import Nimble
 | 
						|
import SessionUIKit
 | 
						|
import SessionSnodeKit
 | 
						|
import SessionUtilitiesKit
 | 
						|
 | 
						|
@testable import Session
 | 
						|
 | 
						|
class ThreadDisappearingMessagesSettingsViewModelSpec: QuickSpec {
 | 
						|
    override class func spec() {
 | 
						|
        // MARK: Configuration
 | 
						|
        
 | 
						|
        @TestState var mockStorage: Storage! = SynchronousStorage(
 | 
						|
            customWriter: try! DatabaseQueue(),
 | 
						|
            migrationTargets: [
 | 
						|
                SNUtilitiesKit.self,
 | 
						|
                SNSnodeKit.self,
 | 
						|
                SNMessagingKit.self,
 | 
						|
                SNUIKit.self
 | 
						|
            ],
 | 
						|
            initialData: { db in
 | 
						|
                try SessionThread(
 | 
						|
                    id: "TestId",
 | 
						|
                    variant: .contact
 | 
						|
                ).insert(db)
 | 
						|
            }
 | 
						|
        )
 | 
						|
        @TestState var dependencies: Dependencies! = Dependencies(
 | 
						|
            storage: mockStorage,
 | 
						|
            scheduler: .immediate
 | 
						|
        )
 | 
						|
        @TestState var viewModel: ThreadDisappearingMessagesSettingsViewModel! = ThreadDisappearingMessagesSettingsViewModel(
 | 
						|
            threadId: "TestId",
 | 
						|
            threadVariant: .contact,
 | 
						|
            currentUserIsClosedGroupMember: nil,
 | 
						|
            currentUserIsClosedGroupAdmin: nil,
 | 
						|
            config: DisappearingMessagesConfiguration.defaultWith("TestId"),
 | 
						|
            using: dependencies
 | 
						|
        )
 | 
						|
        
 | 
						|
        @TestState var cancellables: [AnyCancellable]! = [
 | 
						|
            viewModel.tableDataPublisher
 | 
						|
                .receive(on: ImmediateScheduler.shared)
 | 
						|
                .sink(
 | 
						|
                    receiveCompletion: { _ in },
 | 
						|
                    receiveValue: { viewModel.updateTableData($0.0) }
 | 
						|
                )
 | 
						|
        ]
 | 
						|
        
 | 
						|
        // MARK: - a ThreadDisappearingMessagesSettingsViewModel
 | 
						|
        describe("a ThreadDisappearingMessagesSettingsViewModel") {
 | 
						|
            // MARK: -- has the correct title
 | 
						|
            it("has the correct title") {
 | 
						|
                expect(viewModel.title).to(equal("DISAPPEARING_MESSAGES".localized()))
 | 
						|
            }
 | 
						|
            
 | 
						|
            // MARK: -- has the correct number of items
 | 
						|
            it("has the correct number of items") {
 | 
						|
                // The default disappearing messages configure is Off
 | 
						|
                // Should only show one section of Disappearing Messages Type
 | 
						|
                expect(viewModel.tableData.count).to(equal(1))
 | 
						|
                
 | 
						|
                if Features.useNewDisappearingMessagesConfig {
 | 
						|
                    // Off
 | 
						|
                    // Disappear After Read
 | 
						|
                    // Disappear After Send
 | 
						|
                    expect(viewModel.tableData.first?.elements.count).to(equal(3))
 | 
						|
                } else {
 | 
						|
                    // Off
 | 
						|
                    // Legacy
 | 
						|
                    // Disappear After Read
 | 
						|
                    // Disappear After Send
 | 
						|
                    expect(viewModel.tableData.first?.elements.count).to(equal(4))
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            // MARK: -- has the correct default state
 | 
						|
            it("has the correct default state") {
 | 
						|
                // First option is always Off
 | 
						|
                expect(viewModel.tableData.first?.elements.first)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: "DISAPPEARING_MESSAGES_OFF".localized(),
 | 
						|
                                position: .top,
 | 
						|
                                title: "DISAPPEARING_MESSAGES_OFF".localized(),
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { true }
 | 
						|
                                ),
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Disable disappearing messages (Off option)",
 | 
						|
                                    label: "Disable disappearing messages (Off option)"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
                // Last option is always Disappear After Send
 | 
						|
                expect(viewModel.tableData.first?.elements.last)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
 | 
						|
                                position: .bottom,
 | 
						|
                                title: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
 | 
						|
                                subtitle: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION".localized(),
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { false }
 | 
						|
                                ),
 | 
						|
                                isEnabled: Features.useNewDisappearingMessagesConfig,
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Disappear after send option",
 | 
						|
                                    label: "Disappear after send option"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
            }
 | 
						|
            
 | 
						|
            // MARK: -- starts with the correct item active if not default
 | 
						|
            it("starts with the correct item active if not default") {
 | 
						|
                // Test config: Disappear After Send - 2 weeks
 | 
						|
                let config: DisappearingMessagesConfiguration = DisappearingMessagesConfiguration
 | 
						|
                    .defaultWith("TestId")
 | 
						|
                    .with(
 | 
						|
                        isEnabled: true,
 | 
						|
                        durationSeconds: DisappearingMessagesConfiguration.validDurationsSeconds(.disappearAfterSend).last,
 | 
						|
                        type: .disappearAfterSend
 | 
						|
                    )
 | 
						|
                mockStorage.write { db in
 | 
						|
                    _ = try config.saved(db)
 | 
						|
                }
 | 
						|
                viewModel = ThreadDisappearingMessagesSettingsViewModel(
 | 
						|
                    threadId: "TestId",
 | 
						|
                    threadVariant: .contact,
 | 
						|
                    currentUserIsClosedGroupMember: nil,
 | 
						|
                    currentUserIsClosedGroupAdmin: nil,
 | 
						|
                    config: config,
 | 
						|
                    using: dependencies
 | 
						|
                )
 | 
						|
                cancellables.append(
 | 
						|
                    viewModel.tableDataPublisher
 | 
						|
                        .receive(on: ImmediateScheduler.shared)
 | 
						|
                        .sink(
 | 
						|
                            receiveCompletion: { _ in },
 | 
						|
                            receiveValue: { viewModel.updateTableData($0.0) }
 | 
						|
                        )
 | 
						|
                )
 | 
						|
                
 | 
						|
                // Should have 2 sections now: Disappearing Messages Type & Timer
 | 
						|
                expect(viewModel.tableData.count)
 | 
						|
                    .to(equal(2))
 | 
						|
                
 | 
						|
                expect(viewModel.tableData.first?.elements.first)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: "DISAPPEARING_MESSAGES_OFF".localized(),
 | 
						|
                                position: .top,
 | 
						|
                                title: "DISAPPEARING_MESSAGES_OFF".localized(),
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { false }
 | 
						|
                                ),
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Disable disappearing messages (Off option)",
 | 
						|
                                    label: "Disable disappearing messages (Off option)"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
                
 | 
						|
                expect(viewModel.tableData.first?.elements.last)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
 | 
						|
                                position: .bottom,
 | 
						|
                                title: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
 | 
						|
                                subtitle: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION".localized(),
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { true }
 | 
						|
                                ),
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Disappear after send option",
 | 
						|
                                    label: "Disappear after send option"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
                
 | 
						|
                let title: String = (DisappearingMessagesConfiguration.validDurationsSeconds(.disappearAfterSend).last?
 | 
						|
                    .formatted(format: .long))
 | 
						|
                    .defaulting(to: "")
 | 
						|
                expect(viewModel.tableData.last?.elements.last)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: title,
 | 
						|
                                position: .bottom,
 | 
						|
                                title: title,
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { true }
 | 
						|
                                ),
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Time option",
 | 
						|
                                    label: "Time option"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
            }
 | 
						|
            
 | 
						|
            // MARK: -- has no footer button
 | 
						|
            it("has no footer button") {
 | 
						|
                var footerButtonInfo: SessionButton.Info?
 | 
						|
                
 | 
						|
                cancellables.append(
 | 
						|
                    viewModel.footerButtonInfo
 | 
						|
                        .receive(on: ImmediateScheduler.shared)
 | 
						|
                        .sink(
 | 
						|
                            receiveCompletion: { _ in },
 | 
						|
                            receiveValue: { info in footerButtonInfo = info }
 | 
						|
                        )
 | 
						|
                )
 | 
						|
                
 | 
						|
                expect(footerButtonInfo).to(beNil())
 | 
						|
            }
 | 
						|
            
 | 
						|
            // MARK: -- can change to another setting and change back
 | 
						|
            it("can change to another setting and change back") {
 | 
						|
                // Test config: Disappear After Send - 2 weeks
 | 
						|
                let config: DisappearingMessagesConfiguration = DisappearingMessagesConfiguration
 | 
						|
                    .defaultWith("TestId")
 | 
						|
                    .with(
 | 
						|
                        isEnabled: true,
 | 
						|
                        durationSeconds: DisappearingMessagesConfiguration.validDurationsSeconds(.disappearAfterSend).last,
 | 
						|
                        type: .disappearAfterSend
 | 
						|
                    )
 | 
						|
                mockStorage.write { db in
 | 
						|
                    _ = try config.saved(db)
 | 
						|
                }
 | 
						|
                viewModel = ThreadDisappearingMessagesSettingsViewModel(
 | 
						|
                    threadId: "TestId",
 | 
						|
                    threadVariant: .contact,
 | 
						|
                    currentUserIsClosedGroupMember: nil,
 | 
						|
                    currentUserIsClosedGroupAdmin: nil,
 | 
						|
                    config: config,
 | 
						|
                    using: dependencies
 | 
						|
                )
 | 
						|
                cancellables.append(
 | 
						|
                    viewModel.tableDataPublisher
 | 
						|
                        .receive(on: ImmediateScheduler.shared)
 | 
						|
                        .sink(
 | 
						|
                            receiveCompletion: { _ in },
 | 
						|
                            receiveValue: { viewModel.updateTableData($0.0) }
 | 
						|
                        )
 | 
						|
                )
 | 
						|
                
 | 
						|
                // Change to another setting
 | 
						|
                viewModel.tableData.first?.elements.first?.onTap?()
 | 
						|
                // Change back
 | 
						|
                viewModel.tableData.first?.elements.last?.onTap?()
 | 
						|
                
 | 
						|
                expect(viewModel.tableData.first?.elements.last)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
 | 
						|
                                position: .bottom,
 | 
						|
                                title: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
 | 
						|
                                subtitle: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION".localized(),
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { true }
 | 
						|
                                ),
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Disappear after send option",
 | 
						|
                                    label: "Disappear after send option"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
                
 | 
						|
                let title: String = (DisappearingMessagesConfiguration.validDurationsSeconds(.disappearAfterSend).last?
 | 
						|
                    .formatted(format: .long))
 | 
						|
                    .defaulting(to: "")
 | 
						|
                expect(viewModel.tableData.last?.elements.last)
 | 
						|
                    .to(
 | 
						|
                        equal(
 | 
						|
                            SessionCell.Info(
 | 
						|
                                id: title,
 | 
						|
                                position: .bottom,
 | 
						|
                                title: title,
 | 
						|
                                rightAccessory: .radio(
 | 
						|
                                    isSelected: { true }
 | 
						|
                                ),
 | 
						|
                                accessibility: Accessibility(
 | 
						|
                                    identifier: "Time option",
 | 
						|
                                    label: "Time option"
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                    )
 | 
						|
                
 | 
						|
                var footerButtonInfo: SessionButton.Info?
 | 
						|
                
 | 
						|
                cancellables.append(
 | 
						|
                    viewModel.footerButtonInfo
 | 
						|
                        .receive(on: ImmediateScheduler.shared)
 | 
						|
                        .sink(
 | 
						|
                            receiveCompletion: { _ in },
 | 
						|
                            receiveValue: { info in footerButtonInfo = info }
 | 
						|
                        )
 | 
						|
                )
 | 
						|
                
 | 
						|
                expect(footerButtonInfo).to(beNil())
 | 
						|
            }
 | 
						|
            
 | 
						|
            // MARK: -- when changed from the previous setting
 | 
						|
            context("when changed from the previous setting") {
 | 
						|
                @TestState var footerButtonInfo: SessionButton.Info?
 | 
						|
                
 | 
						|
                beforeEach {
 | 
						|
                    cancellables.append(
 | 
						|
                        viewModel.footerButtonInfo
 | 
						|
                            .receive(on: ImmediateScheduler.shared)
 | 
						|
                            .sink(
 | 
						|
                                receiveCompletion: { _ in },
 | 
						|
                                receiveValue: { info in footerButtonInfo = info }
 | 
						|
                            )
 | 
						|
                    )
 | 
						|
                    
 | 
						|
                    viewModel.tableData.first?.elements.last?.onTap?()
 | 
						|
                }
 | 
						|
                
 | 
						|
                // MARK: ---- shows the set button
 | 
						|
                it("shows the set button") {
 | 
						|
                    expect(footerButtonInfo)
 | 
						|
                        .to(
 | 
						|
                            equal(
 | 
						|
                                SessionButton.Info(
 | 
						|
                                    style: .bordered,
 | 
						|
                                    title: "DISAPPERING_MESSAGES_SAVE_TITLE".localized(),
 | 
						|
                                    isEnabled: true,
 | 
						|
                                    accessibility: Accessibility(
 | 
						|
                                        identifier: "Set button",
 | 
						|
                                        label: "Set button"
 | 
						|
                                    ),
 | 
						|
                                    minWidth: 110,
 | 
						|
                                    onTap: {}
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
                        )
 | 
						|
                }
 | 
						|
 | 
						|
                // MARK: ---- and saving
 | 
						|
                context("and saving") {
 | 
						|
                    // MARK: ------ dismisses the screen
 | 
						|
                    it("dismisses the screen") {
 | 
						|
                        var didDismissScreen: Bool = false
 | 
						|
                        
 | 
						|
                        cancellables.append(
 | 
						|
                            viewModel.navigatableState.dismissScreen
 | 
						|
                                .receive(on: ImmediateScheduler.shared)
 | 
						|
                                .sink(
 | 
						|
                                    receiveCompletion: { _ in },
 | 
						|
                                    receiveValue: { _ in didDismissScreen = true }
 | 
						|
                                )
 | 
						|
                        )
 | 
						|
                        
 | 
						|
                        footerButtonInfo?.onTap()
 | 
						|
                        
 | 
						|
                        expect(didDismissScreen).to(beTrue())
 | 
						|
                    }
 | 
						|
                    
 | 
						|
                    // MARK: ------ saves the updated config
 | 
						|
                    it("saves the updated config") {
 | 
						|
                        footerButtonInfo?.onTap()
 | 
						|
                        
 | 
						|
                        let updatedConfig: DisappearingMessagesConfiguration? = mockStorage.read { db in
 | 
						|
                            try DisappearingMessagesConfiguration.fetchOne(db, id: "TestId")
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        expect(updatedConfig?.isEnabled).to(beTrue())
 | 
						|
                        expect(updatedConfig?.durationSeconds)
 | 
						|
                            .to(equal(DisappearingMessagesConfiguration.DefaultDuration.disappearAfterSend.seconds))
 | 
						|
                        expect(updatedConfig?.type).to(equal(.disappearAfterSend))
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |