Guard string tables against silent corruption
A .strings value may span several physical lines, so deleting such an entry line by line leaves orphaned lines that the parser folds into the preceding value. Every key behind that point then disappears at runtime while plutil -lint still reports OK. Tab titles are looked up without a defaultValue:, so the tab bar rendered raw keys like "tab.overview" while the rest of the UI fell back to its English defaults. LocalizationIntegrityTests parses each table out of the app bundle and fails on multi-line values, on missing keys that have no fallback, and on leftover cable.pro.* entries. LocalizedTabBarUITests launches the app in German and asserts the tab bar is translated.
This commit is contained in:
62
CableUITestsScreenshot/LocalizedTabBarUITests.swift
Normal file
62
CableUITestsScreenshot/LocalizedTabBarUITests.swift
Normal file
@@ -0,0 +1,62 @@
|
||||
import XCTest
|
||||
|
||||
/// Reproduces the regression where the tab bar rendered raw keys ("tab.overview") because a
|
||||
/// malformed entry in Localizable.strings hid every key behind it. The tab titles are looked up
|
||||
/// without a `defaultValue:`, so a broken table is immediately visible here.
|
||||
final class LocalizedTabBarUITests: XCTestCase {
|
||||
|
||||
override func setUpWithError() throws {
|
||||
try super.setUpWithError()
|
||||
continueAfterFailure = false
|
||||
XCUIDevice.shared.orientation = .portrait
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testTabBarIsLocalizedInGerman() throws {
|
||||
let app = XCUIApplication()
|
||||
app.launchArguments = [
|
||||
"--uitest-reset-data",
|
||||
"--uitest-sample-data",
|
||||
"-AppleLanguages", "(de)",
|
||||
"-AppleLocale", "de_DE",
|
||||
]
|
||||
app.launch()
|
||||
|
||||
openFirstSystem(in: app)
|
||||
|
||||
let expected = ["Übersicht", "Verbraucher", "Batterien", "Ladegeräte"]
|
||||
for title in expected {
|
||||
XCTAssertTrue(
|
||||
app.buttons[title].waitForExistence(timeout: 15),
|
||||
"Tab \"\(title)\" is missing — the German string table is not being read"
|
||||
)
|
||||
}
|
||||
|
||||
for rawKey in ["tab.overview", "tab.components", "tab.batteries", "tab.chargers"] {
|
||||
XCTAssertFalse(
|
||||
app.buttons[rawKey].exists,
|
||||
"Tab bar shows the raw key \(rawKey) instead of a translation"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func openFirstSystem(in app: XCUIApplication) {
|
||||
let list: XCUIElement
|
||||
if app.collectionViews["systems-list"].waitForExistence(timeout: 15) {
|
||||
list = app.collectionViews["systems-list"]
|
||||
} else {
|
||||
list = app.collectionViews.firstMatch
|
||||
}
|
||||
XCTAssertTrue(list.waitForExistence(timeout: 15))
|
||||
|
||||
let firstCell = list.cells.element(boundBy: 0)
|
||||
XCTAssertTrue(firstCell.waitForExistence(timeout: 10))
|
||||
|
||||
let cellButton = firstCell.buttons.firstMatch
|
||||
if cellButton.exists {
|
||||
cellButton.tap()
|
||||
} else {
|
||||
firstCell.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user