mirror of https://github.com/oxen-io/session-ios
Merge branch 'updated-user-config-handling' into disappearing-message-redesign
commit
0b0371e769
@ -0,0 +1,12 @@
|
||||
@@ -41,0 +41,11 @@
|
||||
+ # Skip the rsync step for the WebRTC-lib in simulator builds
|
||||
+ if [[ "$PLATFORM_NAME" == "iphonesimulator" ]] && [[ "$source" == *WebRTC.framework* ]]; then
|
||||
+ if [[ -f "${source}/../already_rsynced.nonce" ]]; then
|
||||
+ echo "Already rsynced WebRTC, skipping"
|
||||
+ return 0
|
||||
+ fi
|
||||
+
|
||||
+ echo "About to rsync a simulator WebRTC, creating nonce to prevent future rsyncing"
|
||||
+ touch "${source}/../already_rsynced.nonce"
|
||||
+ fi
|
||||
+
|
@ -0,0 +1,334 @@
|
||||
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import Quick
|
||||
import Nimble
|
||||
import SessionUtilitiesKit
|
||||
|
||||
@testable import SessionMessagingKit
|
||||
|
||||
class SessionThreadViewModelSpec: QuickSpec {
|
||||
public struct TestMessage: Codable, Equatable, FetchableRecord, PersistableRecord, TableRecord, ColumnExpressible {
|
||||
public static var databaseTableName: String { "testMessage" }
|
||||
|
||||
public typealias Columns = CodingKeys
|
||||
public enum CodingKeys: String, CodingKey, ColumnExpression {
|
||||
case body
|
||||
}
|
||||
|
||||
public let body: String
|
||||
}
|
||||
|
||||
// MARK: - Spec
|
||||
|
||||
override func spec() {
|
||||
describe("a SessionThreadViewModel") {
|
||||
var mockStorage: Storage!
|
||||
|
||||
beforeEach {
|
||||
mockStorage = SynchronousStorage(
|
||||
customWriter: try! DatabaseQueue()
|
||||
)
|
||||
|
||||
mockStorage.write { db in
|
||||
try db.create(table: TestMessage.self) { t in
|
||||
t.column(.body, .text).notNull()
|
||||
}
|
||||
|
||||
try db.create(virtualTable: TestMessage.fullTextSearchTableName, using: FTS5()) { t in
|
||||
t.synchronize(withTable: TestMessage.databaseTableName)
|
||||
t.tokenizer = .porter(wrapping: .unicode61())
|
||||
|
||||
t.column(TestMessage.Columns.body.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - when processing a search term
|
||||
context("when processing a search term") {
|
||||
// MARK: -- correctly generates a safe search term
|
||||
it("correctly generates a safe search term") {
|
||||
expect(SessionThreadViewModel.searchSafeTerm("Test")).to(equal("\"Test\""))
|
||||
}
|
||||
|
||||
// MARK: -- standardises odd quote characters
|
||||
it("standardises odd quote characters") {
|
||||
expect(SessionThreadViewModel.standardQuotes("\"")).to(equal("\""))
|
||||
expect(SessionThreadViewModel.standardQuotes("”")).to(equal("\""))
|
||||
expect(SessionThreadViewModel.standardQuotes("“")).to(equal("\""))
|
||||
}
|
||||
|
||||
// MARK: -- splits on the space character
|
||||
it("splits on the space character") {
|
||||
expect(SessionThreadViewModel.searchTermParts("Test Message"))
|
||||
.to(equal([
|
||||
"\"Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- surrounds each split term with quotes
|
||||
it("surrounds each split term with quotes") {
|
||||
expect(SessionThreadViewModel.searchTermParts("Test Message"))
|
||||
.to(equal([
|
||||
"\"Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- keeps words within quotes together
|
||||
it("keeps words within quotes together") {
|
||||
expect(SessionThreadViewModel.searchTermParts("This \"is a Test\" Message"))
|
||||
.to(equal([
|
||||
"\"This\"",
|
||||
"\"is a Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
expect(SessionThreadViewModel.searchTermParts("\"This is\" a Test Message"))
|
||||
.to(equal([
|
||||
"\"This is\"",
|
||||
"\"a\"",
|
||||
"\"Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
expect(SessionThreadViewModel.searchTermParts("\"This is\" \"a Test\" Message"))
|
||||
.to(equal([
|
||||
"\"This is\"",
|
||||
"\"a Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
expect(SessionThreadViewModel.searchTermParts("\"This is\" a \"Test Message\""))
|
||||
.to(equal([
|
||||
"\"This is\"",
|
||||
"\"a\"",
|
||||
"\"Test Message\""
|
||||
]))
|
||||
expect(SessionThreadViewModel.searchTermParts("\"This is\"\" a \"Test Message"))
|
||||
.to(equal([
|
||||
"\"This is\"",
|
||||
"\" a \"",
|
||||
"\"Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- keeps words within weird quotes together
|
||||
it("keeps words within weird quotes together") {
|
||||
expect(SessionThreadViewModel.searchTermParts("This ”is a Test“ Message"))
|
||||
.to(equal([
|
||||
"\"This\"",
|
||||
"\"is a Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- removes extra whitespace
|
||||
it("removes extra whitespace") {
|
||||
expect(SessionThreadViewModel.searchTermParts(" Test Message "))
|
||||
.to(equal([
|
||||
"\"Test\"",
|
||||
"\"Message\""
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - when searching
|
||||
context("when searching") {
|
||||
beforeEach {
|
||||
mockStorage.write { db in
|
||||
try TestMessage(body: "Test").insert(db)
|
||||
try TestMessage(body: "Test123").insert(db)
|
||||
try TestMessage(body: "Test234").insert(db)
|
||||
try TestMessage(body: "Test Test123").insert(db)
|
||||
try TestMessage(body: "Test Test123 Test234").insert(db)
|
||||
try TestMessage(body: "Test Test234").insert(db)
|
||||
try TestMessage(body: "Test Test234 Test123").insert(db)
|
||||
try TestMessage(body: "This is a Test Message").insert(db)
|
||||
try TestMessage(body: "is a Message This Test").insert(db)
|
||||
try TestMessage(body: "this message is a test").insert(db)
|
||||
try TestMessage(
|
||||
body: "This content is something which includes a combination of test words found in another message"
|
||||
)
|
||||
.insert(db)
|
||||
try TestMessage(body: "Do test messages contain content?").insert(db)
|
||||
try TestMessage(body: "Is messaging awesome?").insert(db)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -- returns results
|
||||
it("returns results") {
|
||||
let results = mockStorage.read { db in
|
||||
let pattern: FTS5Pattern = try SessionThreadViewModel.pattern(
|
||||
db,
|
||||
searchTerm: "Message",
|
||||
forTable: TestMessage.self
|
||||
)
|
||||
|
||||
return try SQLRequest<TestMessage>(literal: """
|
||||
SELECT *
|
||||
FROM testMessage
|
||||
JOIN testMessage_fts ON (
|
||||
testMessage_fts.rowId = testMessage.rowId AND
|
||||
testMessage_fts.body MATCH \(pattern)
|
||||
)
|
||||
""").fetchAll(db)
|
||||
}
|
||||
|
||||
expect(results)
|
||||
.to(equal([
|
||||
TestMessage(body: "This is a Test Message"),
|
||||
TestMessage(body: "is a Message This Test"),
|
||||
TestMessage(body: "this message is a test"),
|
||||
TestMessage(body: "This content is something which includes a combination of test words found in another message"),
|
||||
TestMessage(body: "Do test messages contain content?"),
|
||||
TestMessage(body: "Is messaging awesome?")
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- adds a wildcard to the final part
|
||||
it("adds a wildcard to the final part") {
|
||||
let results = mockStorage.read { db in
|
||||
let pattern: FTS5Pattern = try SessionThreadViewModel.pattern(
|
||||
db,
|
||||
searchTerm: "This mes",
|
||||
forTable: TestMessage.self
|
||||
)
|
||||
|
||||
return try SQLRequest<TestMessage>(literal: """
|
||||
SELECT *
|
||||
FROM testMessage
|
||||
JOIN testMessage_fts ON (
|
||||
testMessage_fts.rowId = testMessage.rowId AND
|
||||
testMessage_fts.body MATCH \(pattern)
|
||||
)
|
||||
""").fetchAll(db)
|
||||
}
|
||||
|
||||
expect(results)
|
||||
.to(equal([
|
||||
TestMessage(body: "This is a Test Message"),
|
||||
TestMessage(body: "is a Message This Test"),
|
||||
TestMessage(body: "this message is a test"),
|
||||
TestMessage(body: "This content is something which includes a combination of test words found in another message"),
|
||||
TestMessage(body: "Do test messages contain content?"),
|
||||
TestMessage(body: "Is messaging awesome?")
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- does not add a wildcard to other parts
|
||||
it("does not add a wildcard to other parts") {
|
||||
let results = mockStorage.read { db in
|
||||
let pattern: FTS5Pattern = try SessionThreadViewModel.pattern(
|
||||
db,
|
||||
searchTerm: "mes Random",
|
||||
forTable: TestMessage.self
|
||||
)
|
||||
|
||||
return try SQLRequest<TestMessage>(literal: """
|
||||
SELECT *
|
||||
FROM testMessage
|
||||
JOIN testMessage_fts ON (
|
||||
testMessage_fts.rowId = testMessage.rowId AND
|
||||
testMessage_fts.body MATCH \(pattern)
|
||||
)
|
||||
""").fetchAll(db)
|
||||
}
|
||||
|
||||
expect(results)
|
||||
.to(beEmpty())
|
||||
}
|
||||
|
||||
// MARK: -- finds similar words without the wildcard due to the porter tokenizer
|
||||
it("finds similar words without the wildcard due to the porter tokenizer") {
|
||||
let results = mockStorage.read { db in
|
||||
let pattern: FTS5Pattern = try SessionThreadViewModel.pattern(
|
||||
db,
|
||||
searchTerm: "message z",
|
||||
forTable: TestMessage.self
|
||||
)
|
||||
|
||||
return try SQLRequest<TestMessage>(literal: """
|
||||
SELECT *
|
||||
FROM testMessage
|
||||
JOIN testMessage_fts ON (
|
||||
testMessage_fts.rowId = testMessage.rowId AND
|
||||
testMessage_fts.body MATCH \(pattern)
|
||||
)
|
||||
""").fetchAll(db)
|
||||
}
|
||||
|
||||
expect(results)
|
||||
.to(equal([
|
||||
TestMessage(body: "This is a Test Message"),
|
||||
TestMessage(body: "is a Message This Test"),
|
||||
TestMessage(body: "this message is a test"),
|
||||
TestMessage(
|
||||
body: "This content is something which includes a combination of test words found in another message"
|
||||
),
|
||||
TestMessage(body: "Do test messages contain content?"),
|
||||
TestMessage(body: "Is messaging awesome?")
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- finds results containing the words regardless of the order
|
||||
it("finds results containing the words regardless of the order") {
|
||||
let results = mockStorage.read { db in
|
||||
let pattern: FTS5Pattern = try SessionThreadViewModel.pattern(
|
||||
db,
|
||||
searchTerm: "is a message",
|
||||
forTable: TestMessage.self
|
||||
)
|
||||
|
||||
return try SQLRequest<TestMessage>(literal: """
|
||||
SELECT *
|
||||
FROM testMessage
|
||||
JOIN testMessage_fts ON (
|
||||
testMessage_fts.rowId = testMessage.rowId AND
|
||||
testMessage_fts.body MATCH \(pattern)
|
||||
)
|
||||
""").fetchAll(db)
|
||||
}
|
||||
|
||||
expect(results)
|
||||
.to(equal([
|
||||
TestMessage(body: "This is a Test Message"),
|
||||
TestMessage(body: "is a Message This Test"),
|
||||
TestMessage(body: "this message is a test"),
|
||||
TestMessage(
|
||||
body: "This content is something which includes a combination of test words found in another message"
|
||||
),
|
||||
TestMessage(body: "Do test messages contain content?"),
|
||||
TestMessage(body: "Is messaging awesome?")
|
||||
]))
|
||||
}
|
||||
|
||||
// MARK: -- does not find quoted parts out of order
|
||||
it("does not find quoted parts out of order") {
|
||||
let results = mockStorage.read { db in
|
||||
let pattern: FTS5Pattern = try SessionThreadViewModel.pattern(
|
||||
db,
|
||||
searchTerm: "\"this is a\" \"test message\"",
|
||||
forTable: TestMessage.self
|
||||
)
|
||||
|
||||
return try SQLRequest<TestMessage>(literal: """
|
||||
SELECT *
|
||||
FROM testMessage
|
||||
JOIN testMessage_fts ON (
|
||||
testMessage_fts.rowId = testMessage.rowId AND
|
||||
testMessage_fts.body MATCH \(pattern)
|
||||
)
|
||||
""").fetchAll(db)
|
||||
}
|
||||
|
||||
expect(results)
|
||||
.to(equal([
|
||||
TestMessage(body: "This is a Test Message"),
|
||||
TestMessage(body: "Do test messages contain content?")
|
||||
]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue