365 lines
25 KiB
Swift
365 lines
25 KiB
Swift
//
|
||
// Copyright 2022 Signal Messenger, LLC
|
||
// SPDX-License-Identifier: AGPL-3.0-only
|
||
//
|
||
|
||
import XCTest
|
||
import SignalServiceKit
|
||
|
||
final class StringTest: XCTestCase {
|
||
func test_digitsOnly() {
|
||
XCTAssertEqual("".digitsOnly(), "")
|
||
XCTAssertEqual("abc".digitsOnly(), "")
|
||
XCTAssertEqual("123".digitsOnly(), "123")
|
||
XCTAssertEqual("-1.23".digitsOnly(), "123")
|
||
XCTAssertEqual("1x2 3".digitsOnly(), "123")
|
||
XCTAssertEqual("١23".digitsOnly(), "١23")
|
||
XCTAssertEqual("1️⃣23".digitsOnly(), "123")
|
||
}
|
||
|
||
func test_asciiDigitsOnly() {
|
||
XCTAssertEqual("".asciiDigitsOnly, "")
|
||
XCTAssertEqual("abc".asciiDigitsOnly, "")
|
||
XCTAssertEqual("123".asciiDigitsOnly, "123")
|
||
XCTAssertEqual("-1.23".asciiDigitsOnly, "123")
|
||
XCTAssertEqual("1x2 3".asciiDigitsOnly, "123")
|
||
XCTAssertEqual("1١23".asciiDigitsOnly, "123")
|
||
XCTAssertEqual("19️⃣23".asciiDigitsOnly, "123")
|
||
XCTAssertEqual("6️⃣123".asciiDigitsOnly, "123")
|
||
}
|
||
|
||
func test_isAsciiDigitsOnly() throws {
|
||
XCTAssertTrue("".isAsciiDigitsOnly)
|
||
XCTAssertTrue("1".isAsciiDigitsOnly)
|
||
XCTAssertTrue("1234567890".isAsciiDigitsOnly)
|
||
XCTAssertFalse(" ".isAsciiDigitsOnly)
|
||
XCTAssertFalse("x".isAsciiDigitsOnly)
|
||
XCTAssertFalse("x1".isAsciiDigitsOnly)
|
||
XCTAssertFalse("1x".isAsciiDigitsOnly)
|
||
XCTAssertFalse("1.2".isAsciiDigitsOnly)
|
||
XCTAssertFalse("1️⃣".isAsciiDigitsOnly)
|
||
XCTAssertFalse("١٢٣".isAsciiDigitsOnly)
|
||
}
|
||
|
||
func test_caesar() {
|
||
XCTAssertEqual("abc", try! "abc".caesar(shift: 0))
|
||
XCTAssertEqual("abc", try! "abc".caesar(shift: 127))
|
||
|
||
XCTAssertEqual("bcd", try! "abc".caesar(shift: 1))
|
||
XCTAssertEqual("bcd", try! "abc".caesar(shift: 128))
|
||
|
||
XCTAssertEqual("z{b", try! "yza".caesar(shift: 1))
|
||
XCTAssertEqual("|}d", try! "yza".caesar(shift: 3))
|
||
XCTAssertEqual("ef=g", try! "bc:d".caesar(shift: 3))
|
||
|
||
let shifted = try! "abc".caesar(shift: 32)
|
||
let roundTrip = try! shifted.caesar(shift: 127 - 32)
|
||
XCTAssertEqual("abc", roundTrip)
|
||
}
|
||
|
||
func test_encodedForSelector() {
|
||
XCTAssertEqual("cnN0", "abc".encodedForSelector)
|
||
XCTAssertEqual("abc", "abc".encodedForSelector!.decodedForSelector)
|
||
|
||
XCTAssertNotEqual("abcWithFoo:bar:", "abcWithFoo:bar:".encodedForSelector)
|
||
XCTAssertEqual("abcWithFoo:bar:", "abcWithFoo:bar:".encodedForSelector!.decodedForSelector)
|
||
|
||
XCTAssertNotEqual("abcWithFoo:bar:zaz1:", "abcWithFoo:bar:zaz1:".encodedForSelector)
|
||
XCTAssertEqual("abcWithFoo:bar:zaz1:", "abcWithFoo:bar:zaz1:".encodedForSelector!.decodedForSelector)
|
||
}
|
||
|
||
func test_directionalAppend() {
|
||
// We used to have a rtlSafeAppend helper, but it didn't behave quite like expected
|
||
// because iOS tries to be smart about the language of the string you're appending to.
|
||
//
|
||
// Sanity check that the iOS methods are doing what we want.
|
||
|
||
// Basic tests, "a" + "b" = "ab", etc.
|
||
XCTAssertEqual("a" + "b", "ab")
|
||
XCTAssertEqual("hello" + " " + "world", "hello world")
|
||
XCTAssertEqual("a" + " " + "1" + " " + "b", "a 1 b")
|
||
|
||
XCTAssertEqual("ا" + "ب", "اب")
|
||
XCTAssertEqual("مرحبا" + " " + "بالعالم", "مرحبا بالعالم")
|
||
XCTAssertEqual("ا" + " " + "1" + " " + "ب", "ا 1 ب")
|
||
|
||
// Test a common usage, similar to `formatPastTimestampRelativeToNow` where we append a time to a date.
|
||
|
||
let testTime = "9:41"
|
||
|
||
let testStrings: [(day: String, expectedConcatentation: String)] = [
|
||
// LTR Tests
|
||
("Today", "Today 9:41"), // English
|
||
("Heute", "Heute 9:41"), // German
|
||
|
||
// RTL Tests
|
||
("اليوم", "اليوم 9:41"), // Arabic
|
||
("היום", "היום 9:41") // Hebrew
|
||
]
|
||
|
||
for (day, expectedConcatentation) in testStrings {
|
||
XCTAssertEqual(day + " " + testTime, expectedConcatentation)
|
||
XCTAssertEqual((day).appending(" ").appending(testTime), expectedConcatentation)
|
||
XCTAssertEqual(NSAttributedString(string: day) + " " + testTime, NSAttributedString(string: expectedConcatentation))
|
||
}
|
||
}
|
||
|
||
func test_formatDurationLossless() {
|
||
let secondsPerMinute: UInt32 = 60
|
||
let secondsPerHour: UInt32 = secondsPerMinute * 60
|
||
let secondsPerDay: UInt32 = secondsPerHour * 24
|
||
let secondsPerWeek: UInt32 = secondsPerDay * 7
|
||
let secondsPerYear: UInt32 = secondsPerDay * 365
|
||
|
||
let format: (UInt32) -> String = String.formatDurationLossless
|
||
|
||
XCTAssertEqual(format(0), "0 seconds")
|
||
XCTAssertEqual(format(1), "1 second")
|
||
XCTAssertEqual(format(2), "2 seconds")
|
||
|
||
XCTAssertEqual(format(1 * secondsPerMinute - 1), "59 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerMinute), "1 minute")
|
||
XCTAssertEqual(format(1 * secondsPerMinute + 1), "1 minute, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerMinute + 2), "1 minute, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerMinute - 1), "1 minute, 59 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerMinute), "2 minutes")
|
||
XCTAssertEqual(format(2 * secondsPerMinute + 1), "2 minutes, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerMinute + 2), "2 minutes, 2 seconds")
|
||
|
||
XCTAssertEqual(format(1 * secondsPerHour - 1), "59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerHour), "1 hour")
|
||
XCTAssertEqual(format(1 * secondsPerHour + 1), "1 hour, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerHour + 2), "1 hour, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerHour + 1 * secondsPerMinute + 1), "1 hour, 1 minute, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerHour + 1 * secondsPerMinute + 2), "1 hour, 1 minute, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerHour + 2 * secondsPerMinute + 1), "1 hour, 2 minutes, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerHour + 2 * secondsPerMinute + 2), "1 hour, 2 minutes, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerHour - 1), "1 hour, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerHour), "2 hours")
|
||
XCTAssertEqual(format(2 * secondsPerHour + 1), "2 hours, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerHour + 2), "2 hours, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerHour + 1 * secondsPerMinute + 1), "2 hours, 1 minute, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerHour + 1 * secondsPerMinute + 2), "2 hours, 1 minute, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerHour + 2 * secondsPerMinute + 1), "2 hours, 2 minutes, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerHour + 2 * secondsPerMinute + 2), "2 hours, 2 minutes, 2 seconds")
|
||
|
||
XCTAssertEqual(format(1 * secondsPerDay - 1), "23 hours, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerDay), "1 day")
|
||
XCTAssertEqual(format(1 * secondsPerDay + 1), "1 day, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerDay + 2), "1 day, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerDay + 1 * secondsPerHour + 1), "1 day, 1 hour, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerDay + 1 * secondsPerHour + 2), "1 day, 1 hour, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerDay + 2 * secondsPerHour + 1), "1 day, 2 hours, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerDay + 2 * secondsPerHour + 2), "1 day, 2 hours, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerDay - 1), "1 day, 23 hours, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerDay), "2 days")
|
||
XCTAssertEqual(format(2 * secondsPerDay + 1), "2 days, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerDay + 2), "2 days, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerDay + 1 * secondsPerHour + 1), "2 days, 1 hour, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerDay + 1 * secondsPerHour + 2), "2 days, 1 hour, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerDay + 2 * secondsPerHour + 1), "2 days, 2 hours, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerDay + 2 * secondsPerHour + 2), "2 days, 2 hours, 2 seconds")
|
||
|
||
XCTAssertEqual(format(1 * secondsPerWeek - 1), "6 days, 23 hours, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerWeek), "1 week")
|
||
XCTAssertEqual(format(1 * secondsPerWeek + 1), "1 week, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerWeek + 2), "1 week, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerWeek + 1 * secondsPerDay + 1), "1 week, 1 day, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerWeek + 1 * secondsPerDay + 2), "1 week, 1 day, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerWeek + 2 * secondsPerDay + 1), "1 week, 2 days, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerWeek + 2 * secondsPerDay + 2), "1 week, 2 days, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerWeek - 1), "1 week, 6 days, 23 hours, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerWeek), "2 weeks")
|
||
XCTAssertEqual(format(2 * secondsPerWeek + 1), "2 weeks, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerWeek + 2), "2 weeks, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerWeek + 1 * secondsPerDay + 1), "2 weeks, 1 day, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerWeek + 1 * secondsPerDay + 2), "2 weeks, 1 day, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerWeek + 2 * secondsPerDay + 1), "2 weeks, 2 days, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerWeek + 2 * secondsPerDay + 2), "2 weeks, 2 days, 2 seconds")
|
||
|
||
XCTAssertEqual(format(1 * secondsPerYear - 1), "52 weeks, 23 hours, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerYear), "1 year")
|
||
XCTAssertEqual(format(1 * secondsPerYear + 1), "1 year, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerYear + 2), "1 year, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerYear + 1 * secondsPerWeek + 1), "1 year, 1 week, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerYear + 1 * secondsPerWeek + 2), "1 year, 1 week, 2 seconds")
|
||
XCTAssertEqual(format(1 * secondsPerYear + 2 * secondsPerWeek + 1), "1 year, 2 weeks, 1 second")
|
||
XCTAssertEqual(format(1 * secondsPerYear + 2 * secondsPerWeek + 2), "1 year, 2 weeks, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerYear - 1), "1 year, 52 weeks, 23 hours, 59 minutes, 59 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerYear), "2 years")
|
||
XCTAssertEqual(format(2 * secondsPerYear + 1), "2 years, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerYear + 2), "2 years, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerYear + 1 * secondsPerWeek + 1), "2 years, 1 week, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerYear + 1 * secondsPerWeek + 2), "2 years, 1 week, 2 seconds")
|
||
XCTAssertEqual(format(2 * secondsPerYear + 2 * secondsPerWeek + 1), "2 years, 2 weeks, 1 second")
|
||
XCTAssertEqual(format(2 * secondsPerYear + 2 * secondsPerWeek + 2), "2 years, 2 weeks, 2 seconds")
|
||
|
||
let aVeryLongTime = 88 * secondsPerYear + 7 * secondsPerWeek + 6 * secondsPerDay + 5 * secondsPerHour + 4 * secondsPerMinute + 3
|
||
XCTAssertEqual(format(aVeryLongTime), "88 years, 7 weeks, 6 days, 5 hours, 4 minutes, 3 seconds")
|
||
}
|
||
|
||
func testIsStructurallyValidE164() {
|
||
let testCases: [(String, Bool)] = [
|
||
// E164 must have leading +.
|
||
("+5218341639157", true),
|
||
("5218341639157", false),
|
||
("+18018108311", true),
|
||
("18018108311", false),
|
||
// E164 must have exactly 1 leading +.
|
||
("++18018108311", false),
|
||
// E164 must only contains 0-9 arabic digits.
|
||
("+123a456", false),
|
||
("+123\u{0661}456", false), // ARABIC-INDIC DIGIT ONE
|
||
("+123\u{0031}\u{fe0f}\u{20e3}456", false), // KEYCAP DIGIT 1
|
||
// E164 must have at least 1 digit.
|
||
("+1", true),
|
||
("+", false),
|
||
// E164 must have no more than 19 digits.
|
||
("+1234567890123456789", true),
|
||
("+12345678901234567890", false),
|
||
// E164 must not start with a zero
|
||
("+0", false),
|
||
("+0123", false),
|
||
("+3210", true)
|
||
]
|
||
for (inputValue, expectedResult) in testCases {
|
||
XCTAssertEqual(inputValue.isStructurallyValidE164, expectedResult, "\(inputValue)")
|
||
}
|
||
}
|
||
|
||
func test_filterAsE164() {
|
||
XCTAssertEqual("", "".filteredAsE164)
|
||
XCTAssertEqual("", " ".filteredAsE164)
|
||
XCTAssertEqual("", "abc".filteredAsE164)
|
||
XCTAssertEqual("+123123", "abc+123+123zz".filteredAsE164)
|
||
XCTAssertEqual("+123123", ("+123" + "مرحبا بالعالم" + "abc+123zz").filteredAsE164)
|
||
XCTAssertEqual("+123123", "abc+123zz+123".filteredAsE164)
|
||
XCTAssertEqual("+123123", "abc+123zz+123🇨🇦".filteredAsE164)
|
||
XCTAssertEqual("", "🇨🇦".filteredAsE164)
|
||
XCTAssertEqual("1", "1🇨🇦".filteredAsE164)
|
||
XCTAssertEqual("1", "🇨🇦1".filteredAsE164)
|
||
XCTAssertEqual("", "🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦".filteredAsE164)
|
||
XCTAssertEqual("1", "1🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦".filteredAsE164)
|
||
XCTAssertEqual("1", "🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦1".filteredAsE164)
|
||
XCTAssertEqual("", "田".filteredAsE164)
|
||
XCTAssertEqual("1", "1田".filteredAsE164)
|
||
XCTAssertEqual("1", "田1".filteredAsE164)
|
||
XCTAssertEqual("", "田田田田田田田".filteredAsE164)
|
||
XCTAssertEqual("1", "1田田田田田田".filteredAsE164)
|
||
XCTAssertEqual("1", "田田田田田田田1".filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "田中さんにあげて下さい" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "パーティーへ行かないか" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "和製漢語" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "部落格" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "사회과학원 어학연구소" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "찦차를 타고 온 펲시맨과 쑛다리 똠방각하" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "社會科學院語學研究所" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "울란바토르" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𠜎𠜱𠝹𠱓𠱸𠲖𠳏" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "表ポあA鷗ŒéB逍Üߪąñ丂㐀𠀀" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "ヽ༼ຈل͜ຈ༽ノ ヽ༼ຈل͜ຈ༽ノ" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "(。◕ ∀ ◕。)" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "`ィ(´∀`∩" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "__ロ(,_,*)" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "・( ̄∀ ̄)・:*:" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "゚・✿ヾ╲(。◕‿◕。)╱✿・゚" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + ",。・:*:・゜’( ☻ ω ☻ )。・:*:・゜’" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "(╯°□°)╯︵ ┻━┻)" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "(ノಥ益ಥ)ノ ┻━┻" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "┬─┬ノ( º _ ºノ)" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "( ͡° ͜ʖ ͡°)" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "¯\\_(ツ)_/¯" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "😍" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "👩🏽" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "👨🦰 👨🏿🦰 👨🦱 👨🏿🦱 🦹🏿♂️" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "👾 🙇 💁 🙅 🙆 🙋 🙎 🙍" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "🐵 🙈 🙉 🙊" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "❤️ 💔 💌 💕 💞 💓 💗 💖 💘 💝 💟 💜 💛 💚 💙" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "✋🏿 💪🏿 👐🏿 🙌🏿 👏🏿 🙏🏿" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "👨👩👦 👨👩👧👦 👨👨👦 👩👩👧 👨👦 👨👧👦 👩👦 👩👧👦" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "🚾 🆒 🆓 🆕 🆖 🆗 🆙 🏧" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+1230123456789321", ("+123" + "0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 🔟" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "🇺🇸🇷🇺🇸 🇦🇫🇦🇲🇸" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "🇺🇸🇷🇺🇸🇦🇫🇦🇲" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "🇺🇸🇷🇺🇸🇦" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "123" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "١٢٣" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "ثم نفس سقطت وبالتحديد،, جزيرتي باستخدام أن دنو. إذ هنا؟ الستار وتنصيب كان. أهّل ايطاليا، بريطانيا-فرنسا قد أخذ. سليمان، إتفاقية بين ما, يذكر الحدود أي بعد, معاملة بولندا، الإطلاق عل إيو." + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "בְּרֵאשִׁית, בָּרָא אֱלֹהִים, אֵת הַשָּׁמַיִם, וְאֵת הָאָרֶץ" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "הָיְתָהtestالصفحات التّحول" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "﷽" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "ﷺ" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "مُنَاقَشَةُ سُبُلِ اِسْتِخْدَامِ اللُّغَةِ فِي النُّظُمِ الْقَائِمَةِ وَفِيم يَخُصَّ التَّطْبِيقَاتُ الْحاسُوبِيَّةُ،" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+1235321", ("+123" + "الكل في المجمو عة (5)" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "᚛ᚄᚓᚐᚋᚒᚄ ᚑᚄᚂᚑᚏᚅ᚜" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "᚛ ᚜" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "Ṱ̺̺̕o͞ ̷i̲̬͇̪͙n̝̗͕v̟̜̘̦͟o̶̙̰̠kè͚̮̺̪̹̱̤ ̖t̝͕̳̣̻̪͞h̼͓̲̦̳̘̲e͇̣̰̦̬͎ ̢̼̻̱̘h͚͎͙̜̣̲ͅi̦̲̣̰̤v̻͍e̺̭̳̪̰-m̢iͅn̖̺̞̲̯̰d̵̼̟͙̩̼̘̳ ̞̥̱̳̭r̛̗̘e͙p͠r̼̞̻̭̗e̺̠̣͟s̘͇̳͍̝͉e͉̥̯̞̲͚̬͜ǹ̬͎͎̟̖͇̤t͍̬̤͓̼̭͘ͅi̪̱n͠g̴͉ ͏͉ͅc̬̟h͡a̫̻̯͘o̫̟̖͍̙̝͉s̗̦̲.̨̹͈̣" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "̡͓̞ͅI̗̘̦͝n͇͇͙v̮̫ok̲̫̙͈i̖͙̭̹̠̞n̡̻̮̣̺g̲͈͙̭͙̬͎ ̰t͔̦h̞̲e̢̤ ͍̬̲͖f̴̘͕̣è͖ẹ̥̩l͖͔͚i͓͚̦͠n͖͍̗͓̳̮g͍ ̨o͚̪͡f̘̣̬ ̖̘͖̟͙̮c҉͔̫͖͓͇͖ͅh̵̤̣͚͔á̗̼͕ͅo̼̣̥s̱͈̺̖̦̻͢.̛̖̞̠̫̰" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "̗̺͖̹̯͓Ṯ̤͍̥͇͈h̲́e͏͓̼̗̙̼̣͔ ͇̜̱̠͓͍ͅN͕͠e̗̱z̘̝̜̺͙p̤̺̹͍̯͚e̠̻̠͜r̨̤͍̺̖͔̖̖d̠̟̭̬̝͟i̦͖̩͓͔̤a̠̗̬͉̙n͚͜ ̻̞̰͚ͅh̵͉i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+12300321", ("+123" + "00˙Ɩ$-" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "The quick brown fox jumps over the lazy dog" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+1230321", ("+123" + "🏳0🌈️" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "జ్ఞా" + "321+").filteredAsE164)
|
||
XCTAssertEqual("+123321", ("+123" + "گچپژ" + "321+").filteredAsE164)
|
||
}
|
||
|
||
func test_ensureArabicNumerals() {
|
||
let zeroToNineTests: [String] = [
|
||
"০১২৩৪৫৬৭৮৯", // Bengali
|
||
"၀၁၂၃၄၅၆၇၈၉", // Burmese
|
||
"〇一二三四五六七八九", // Chinese (Simplified), Japanese
|
||
"零一二三四五六七八九", // Chinese (Traditional)
|
||
"०१२३४५६७८९", // Devanagari (Sanskrit, Hindi, and other Indian languages)
|
||
"٠١٢٣٤٥٦٧٨٩", // Eastern Arabic
|
||
"૦૧૨૩૪૫૬૭૮૯", // Gujarati
|
||
"੦੧੨੩੪੫੬੭੮੯", // Gurmukhi (Punjabi)
|
||
"೦೧೨೩೪೫೬೭೮೯", // Kannada
|
||
"൦൧൨൩൪൫൬൭൮൯", // Malayalam
|
||
"୦୧୨୩୪୫୬୭୮୯", // Odia
|
||
"۰۱۲۳۴۵۶۷۸۹", // Persian, Urdu
|
||
"௦௧௨௩௪௫௬௭௮௯", // Tamil
|
||
"౦౧౨౩౪౫౬౭౮౯", // Telugu
|
||
"๐๑๒๓๔๕๖๗๘๙", // Thai
|
||
"0123456789", // Western arabic
|
||
]
|
||
|
||
for zeroToNineTest in zeroToNineTests {
|
||
XCTAssertEqual(zeroToNineTest.ensureArabicNumerals, "0123456789")
|
||
}
|
||
|
||
// In mixed strings, only replaces the numerals.
|
||
XCTAssertEqual("نمرا ١٢٣٤٥ يا".ensureArabicNumerals, "نمرا 12345 يا")
|
||
|
||
// Appropriately handles characters that extend across multiple unicode scalars
|
||
XCTAssertEqual("123 👩🏻🔬🧛🏿♀️🤦🏽♀️🏳️🌈 ١٢٣".ensureArabicNumerals, "123 👩🏻🔬🧛🏿♀️🤦🏽♀️🏳️🌈 123")
|
||
|
||
// In strings without numerals, does nothing.
|
||
XCTAssertEqual("a".ensureArabicNumerals, "a")
|
||
XCTAssertEqual("".ensureArabicNumerals, "")
|
||
}
|
||
|
||
func testTrimToGlyphCount() {
|
||
XCTAssertEqual("🥹🥷🥹🥷🥹".trimToGlyphCount(4), "🥹🥷🥹🥷")
|
||
}
|
||
|
||
func testTrimmedIfNeeded() {
|
||
XCTAssertEqual("🥹🥷🥹🥷🥹".trimmedIfNeeded(maxGlyphCount: 4), "🥹🥷🥹🥷")
|
||
XCTAssertEqual("🥹🥷🥹🥷🥹".trimmedIfNeeded(maxGlyphCount: 5), nil)
|
||
XCTAssertEqual("🥹🥷🥹🥷🥹".trimmedIfNeeded(maxGlyphCount: 6), nil)
|
||
}
|
||
|
||
func testTrimToUtf8Count() {
|
||
XCTAssertEqual("🥹🥷🥹🥷🥹".trimToUtf8ByteCount(9), "🥹🥷")
|
||
}
|
||
}
|