import Foundation import RastrilloNative import XCTest @testable import RastrilloApple final class SyncStringsTests: XCTestCase { static let languages = ["ar", "bn", "en", "es", "ga", "hi", "ja", "pt", "ru", "vi", "yue", "zh-Hans"] static let keys = ["sync.saving", "sync.retrying", "sync.offline", "sync.needsSignIn", "sync.signIn", "sync.failed.cannotSave", "sync.failed.tooManyUnsent", "sync.failed.held", "offline.waiting", "offline.durable", "sync.unsentLost"] /// The catalog ships in the same twelve languages as the apps, and no /// language is missing a string: a missing one would show its key. func testEveryLanguageHasEveryString() throws { for language in Self.languages { let strings = try XCTUnwrap(Bundle.module.path(forResource: "Localizable", ofType: "strings", inDirectory: nil, forLocalization: language), language) let table = try XCTUnwrap(NSDictionary(contentsOfFile: strings) as? [String: String], language) XCTAssertEqual(Set(table.keys), Set(Self.keys), language) for (key, value) in table { XCTAssertFalse(value.isEmpty, "\(language) \(key)") } let plurals = try XCTUnwrap(Bundle.module.path(forResource: "Localizable", ofType: "stringsdict", inDirectory: nil, forLocalization: language), language) let rules = try XCTUnwrap(NSDictionary(contentsOfFile: plurals) as? [String: Any], language) XCTAssertEqual(Set(rules.keys), ["sync.offline", "sync.needsSignIn"], language) for key in rules.keys { let rule = try XCTUnwrap((rules[key] as? [String: Any])?["n"] as? [String: String], "\(language) \(key)") XCTAssertNotNil(rule["other"], "\(language) \(key) needs an other form") for (category, text) in rule where !category.hasPrefix("NSString") { XCTAssertTrue(text.contains("%d"), "\(language) \(key) \(category) drops the count") } } } } func testEnglishWording() { let strings = NativeSyncStrings.kit(localization: "en") XCTAssertNil(strings.text(for: .saved), "Saved is silent") XCTAssertEqual(strings.text(for: .saving), "Saving…") XCTAssertEqual(strings.text(for: .offline(pending: 1)), "Offline · 1 pending") XCTAssertEqual(strings.text(for: .offline(pending: 3)), "Offline · 3 pending") XCTAssertEqual(strings.text(for: .retrying(pending: 2)), "Trouble saving · Retrying…") XCTAssertEqual(strings.text(for: .needsSignIn(pending: 2)), "Sign in to send 2 pending") XCTAssertEqual(strings.text(for: .failed(pending: 1, reason: .tooManyUnsent)), "Too many unsent changes to keep on this device. Connect to save.") XCTAssertEqual(strings.text(for: .failed(pending: 1, reason: .cannotSaveOnDevice)), "Can’t save on this device.") XCTAssertEqual(strings.offlineDurable, "You’re offline. Changes are saved on this device and will be sent when you reconnect.") XCTAssertEqual(strings.offlineWaiting, "You’re offline. Waiting for a connection.") } func testPluralRulesAreApplied() { let russian = NativeSyncStrings.kit(localization: "ru") XCTAssertEqual(russian.text(for: .offline(pending: 1)), "Не в сети · 1 ожидает отправки") XCTAssertEqual(russian.text(for: .offline(pending: 3)), "Не в сети · 3 ожидают отправки") let spanish = NativeSyncStrings.kit(localization: "es") XCTAssertEqual(spanish.text(for: .offline(pending: 1)), "Sin conexión · 1 pendiente") XCTAssertEqual(spanish.text(for: .offline(pending: 2)), "Sin conexión · 2 pendientes") } func testAnAppOverridesWithACopy() { var strings = NativeSyncStrings.kit(localization: "en") strings.offline = { "Offline · \($0) cells pending" } XCTAssertEqual(strings.text(for: .offline(pending: 4)), "Offline · 4 cells pending") } }