Fix multilanguage ZIM listing and count, add unit tests

This commit is contained in:
Balazs Perlaki-Horvath 2024-08-04 15:31:43 +02:00 committed by Kelson
parent 2dd19c3e9d
commit eb04143558
4 changed files with 134 additions and 7 deletions

View File

@ -67,7 +67,8 @@ struct Language: Identifiable, Comparable {
let count: Int
init?(code: String, count: Int) {
guard let name = Locale.current.localizedString(forIdentifier: code) else { return nil }
guard let name = Locale.current.localizedString(forIdentifier: code),
count > 0 else { return nil }
self.code = code
self.name = name
self.count = count

View File

@ -0,0 +1,44 @@
// This file is part of Kiwix for iOS & macOS.
//
// Kiwix is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// any later version.
//
// Kiwix is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kiwix; If not, see https://www.gnu.org/licenses/.
import Foundation
/// Helper to collect all language codes with counts,
/// some of them are coma separated entries in the DB, such as "eng,spa,por"
final class LanguageCollector {
private var items: [String: Int] = [:]
func addLanguages(codes: String, count: Int) {
Set(codes.split(separator: ",")).forEach { code in
addLanguage(code: String(code), count: count)
}
}
func languages() -> [Language] {
items.compactMap { (code: String, count: Int) -> Language? in
Language(code: code, count: count)
}.sorted()
}
private func addLanguage(code: String, count: Int) {
if let previousCount = items[code] {
items[code] = previousCount + count
} else {
items[code] = count
}
}
}

View File

@ -0,0 +1,80 @@
// This file is part of Kiwix for iOS & macOS.
//
// Kiwix is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// any later version.
//
// Kiwix is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kiwix; If not, see https://www.gnu.org/licenses/.
import XCTest
@testable import Kiwix
final class LanguageCollectorTest: XCTestCase {
func testEmpty() {
let collector = LanguageCollector()
XCTAssertTrue(collector.languages().isEmpty)
}
func testInvalidEntriesIgnored() {
let collector = LanguageCollector()
collector.addLanguages(codes: "invalid", count: 1)
XCTAssertTrue(collector.languages().isEmpty)
collector.addLanguages(codes: "more,invalid,entries", count: 2)
XCTAssertTrue(collector.languages().isEmpty)
collector.addLanguages(codes: "i_am,invalid,fra", count: 1)
XCTAssertEqual(collector.languages().count, 1)
XCTAssertEqual(collector.languages().first!.name, "French")
}
func testZeroAndNegativeCountsIgnored() {
let collector = LanguageCollector()
collector.addLanguages(codes: "eng", count: 0)
XCTAssertTrue(collector.languages().isEmpty)
collector.addLanguages(codes: "eng,fra", count: -1)
XCTAssertTrue(collector.languages().isEmpty)
}
func testAddingSingleLanguages() {
let collector = LanguageCollector()
collector.addLanguages(codes: "eng", count: 1)
XCTAssertEqual(collector.languages().count, 1)
XCTAssertEqual(collector.languages().first!.name, "English")
XCTAssertEqual(collector.languages().first!.code, "eng")
XCTAssertEqual(collector.languages().first!.count, 1)
}
func testRepeatedLanguagesCodesAreIgnored() {
let collector = LanguageCollector()
collector.addLanguages(codes: "eng,eng", count: 1)
XCTAssertEqual(collector.languages().count, 1)
XCTAssertEqual(collector.languages().first!.count, 1)
}
func testAddingMultipleLanguagesWithCountOne() {
let collector = LanguageCollector()
collector.addLanguages(codes: "fra,eng", count: 1)
XCTAssertEqual(collector.languages().count, 2)
XCTAssertEqual(collector.languages().map { $0.name }, ["English", "French"])
}
func testAddingMultiLanguagesWithVariousCounts() {
let collector = LanguageCollector()
collector.addLanguages(codes: "fra,eng", count: 1)
collector.addLanguages(codes: "spa,por,fra", count: 1)
XCTAssertEqual(collector.languages().count, 4)
XCTAssertEqual(collector.languages(), [
Language(code: "eng", count: 1)!,
Language(code: "fra", count: 2)!,
Language(code: "por", count: 1)!,
Language(code: "spa", count: 1)!
])
}
}

View File

@ -170,13 +170,15 @@ class Languages {
continuation.resume(returning: [])
return
}
let language: [Language] = results.compactMap { result in
guard let result = result as? NSDictionary,
let languageCode = result["languageCode"] as? String,
let count = result["count"] as? Int else { return nil }
return Language(code: languageCode, count: count)
let collector = LanguageCollector()
for result in results {
if let result = result as? NSDictionary,
let languageCodes = result["languageCode"] as? String,
let count = result["count"] as? Int {
collector.addLanguages(codes: languageCodes, count: count)
}
}
continuation.resume(returning: language)
continuation.resume(returning: collector.languages())
}
}
return languages