mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-08-03 20:47:22 -04:00
Fix multilanguage ZIM listing and count, add unit tests
This commit is contained in:
parent
2dd19c3e9d
commit
eb04143558
@ -67,7 +67,8 @@ struct Language: Identifiable, Comparable {
|
|||||||
let count: Int
|
let count: Int
|
||||||
|
|
||||||
init?(code: String, 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.code = code
|
||||||
self.name = name
|
self.name = name
|
||||||
self.count = count
|
self.count = count
|
||||||
|
44
Model/LanguageCollector.swift
Normal file
44
Model/LanguageCollector.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
80
Tests/LanguageCollectorTest.swift
Normal file
80
Tests/LanguageCollectorTest.swift
Normal 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)!
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
@ -170,13 +170,15 @@ class Languages {
|
|||||||
continuation.resume(returning: [])
|
continuation.resume(returning: [])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let language: [Language] = results.compactMap { result in
|
let collector = LanguageCollector()
|
||||||
guard let result = result as? NSDictionary,
|
for result in results {
|
||||||
let languageCode = result["languageCode"] as? String,
|
if let result = result as? NSDictionary,
|
||||||
let count = result["count"] as? Int else { return nil }
|
let languageCodes = result["languageCode"] as? String,
|
||||||
return Language(code: languageCode, count: count)
|
let count = result["count"] as? Int {
|
||||||
|
collector.addLanguages(codes: languageCodes, count: count)
|
||||||
}
|
}
|
||||||
continuation.resume(returning: language)
|
}
|
||||||
|
continuation.resume(returning: collector.languages())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return languages
|
return languages
|
||||||
|
Loading…
x
Reference in New Issue
Block a user