When you compose reply to a message but do not send it, we would persist the text you entered but would lose the quoted message to which you were replying. This commit adds support for persisting that information. ThreadReplyInfo is a new class that uses the key-value store to associate a single optional reference to a message with each thread. The following behaviors are nw: * When you enter the CVC the input toolbar is updated to have the quoted message. * When you exit the CVC the quoted message is saved. * When a thread is deleted, the quoted message is deleted.
186 lines
7.4 KiB
Swift
186 lines
7.4 KiB
Swift
//
|
|
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import XCTest
|
|
@testable import SignalServiceKit
|
|
|
|
extension TSThread {
|
|
@objc
|
|
public class func anyFetchAll(databaseStorage: SDSDatabaseStorage) -> [TSThread] {
|
|
var result = [TSThread]()
|
|
databaseStorage.read { transaction in
|
|
result += anyFetchAll(transaction: transaction)
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
extension TSInteraction {
|
|
@objc
|
|
public class func anyFetchAll(databaseStorage: SDSDatabaseStorage) -> [TSInteraction] {
|
|
var result = [TSInteraction]()
|
|
databaseStorage.read { transaction in
|
|
result += anyFetchAll(transaction: transaction)
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
class SDSDatabaseStorageTest: SSKBaseTestSwift {
|
|
|
|
// MARK: - Test Life Cycle
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
|
|
// ensure local client has necessary "registered" state
|
|
let localE164Identifier = "+13235551234"
|
|
let localUUID = UUID()
|
|
tsAccountManager.registerForTests(withLocalNumber: localE164Identifier, uuid: localUUID)
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
func test_threads() {
|
|
let storage = SDSDatabaseStorage.shared
|
|
|
|
XCTAssertEqual(0, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
let contactAddress = SignalServiceAddress(phoneNumber: "+13213214321")
|
|
let contactThread = TSContactThread(contactAddress: contactAddress)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(0, TSThread.anyFetchAll(transaction: transaction).count)
|
|
contactThread.anyInsert(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
var groupThread: TSGroupThread!
|
|
storage.write { transaction in
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
|
|
groupThread = try! GroupManager.createGroupForTests(members: [contactAddress],
|
|
name: "Test Group",
|
|
transaction: transaction)
|
|
|
|
XCTAssertEqual(2, TSThread.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(2, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(2, TSThread.anyFetchAll(transaction: transaction).count)
|
|
contactThread.anyRemove(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
// Update
|
|
storage.write { transaction in
|
|
let threads = TSThread.anyFetchAll(transaction: transaction)
|
|
guard let firstThread = threads.first else {
|
|
XCTFail("Missing model.")
|
|
return
|
|
}
|
|
XCTAssertNil(firstThread.messageDraft)
|
|
firstThread.update(withDraft: MessageBody(text: "Some draft",
|
|
ranges: .empty),
|
|
replyInfo: nil,
|
|
transaction: transaction)
|
|
}
|
|
storage.read { transaction in
|
|
let threads = TSThread.anyFetchAll(transaction: transaction)
|
|
guard let firstThread = threads.first else {
|
|
XCTFail("Missing model.")
|
|
return
|
|
}
|
|
XCTAssertEqual(firstThread.messageDraft, "Some draft")
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
groupThread.anyRemove(transaction: transaction)
|
|
XCTAssertEqual(0, TSThread.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(0, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
}
|
|
|
|
func test_interactions() {
|
|
let storage = SDSDatabaseStorage.shared
|
|
|
|
XCTAssertEqual(0, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
let contactAddress = SignalServiceAddress(phoneNumber: "+13213214321")
|
|
let contactThread = TSContactThread(contactAddress: contactAddress)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(0, TSThread.anyFetchAll(transaction: transaction).count)
|
|
contactThread.anyInsert(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
XCTAssertEqual(0, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
let message1 = TSOutgoingMessage(in: contactThread, messageBody: "message1", attachmentId: nil)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(0, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
message1.anyInsert(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(1, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
XCTAssertEqual(1, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
let message2 = TSOutgoingMessage(in: contactThread, messageBody: "message2", attachmentId: nil)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(1, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
message2.anyInsert(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(2, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
XCTAssertEqual(2, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(2, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
message1.anyRemove(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(1, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
XCTAssertEqual(1, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
|
|
|
storage.write { transaction in
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(1, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
message2.anyRemove(transaction: transaction)
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(transaction: transaction).count)
|
|
XCTAssertEqual(0, TSInteraction.anyFetchAll(transaction: transaction).count)
|
|
}
|
|
|
|
XCTAssertEqual(1, TSThread.anyFetchAll(databaseStorage: storage).count)
|
|
XCTAssertEqual(0, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
|
}
|
|
}
|