Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ jobs:
if-no-files-found: error
- name: Check Swift formatting
run: xcrun swift-format lint --recursive --strict src tests
- name: Check catalog categories
run: cmake --build --preset release --target CheckCatalogCategories
- name: Check localization catalog
run: |
cmake --build --preset release --target GenerateStrings
Expand Down
64 changes: 64 additions & 0 deletions assets/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,38 @@
}
}
},
"Games": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Games"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "游戏"
}
}
}
},
"Health": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Health"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "健康"
}
}
}
},
"Install": {
"localizations": {
"en": {
Expand Down Expand Up @@ -993,6 +1025,22 @@
}
}
},
"Maps": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Maps"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "地图"
}
}
}
},
"Media": {
"localizations": {
"en": {
Expand Down Expand Up @@ -1345,6 +1393,22 @@
}
}
},
"Reading": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Reading"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "阅读"
}
}
}
},
"Recipe Revision": {
"localizations": {
"en": {
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_executable(SimStore MACOSX_BUNDLE
ContentView.swift
LibrarySection.swift
AppCatalog.swift
CatalogCategory.swift
AppDownload.swift
AppPackage.swift
AppInstaller.swift
Expand Down
27 changes: 27 additions & 0 deletions src/CatalogCategory.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Foundation

enum CatalogCategory: String {
case browser, cloud, communication, games, health, maps, media, productivity, reading, security,
social, utilities

var title: String {
switch self {
case .browser: String(localized: "Browser")
case .cloud: String(localized: "Cloud")
case .communication: String(localized: "Communication")
case .games: String(localized: "Games")
case .health: String(localized: "Health")
case .maps: String(localized: "Maps")
case .media: String(localized: "Media")
case .productivity: String(localized: "Productivity")
case .reading: String(localized: "Reading")
case .security: String(localized: "Security")
case .social: String(localized: "Social")
case .utilities: String(localized: "Utilities")
}
}

static func title(_ category: String) -> String {
Self(rawValue: category)?.title ?? category
}
}
16 changes: 0 additions & 16 deletions src/CatalogPresentation.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
import SwiftUI

enum CatalogCategory {
static func title(_ category: String) -> String {
switch category {
case "browser": String(localized: "Browser")
case "cloud": String(localized: "Cloud")
case "communication": String(localized: "Communication")
case "media": String(localized: "Media")
case "productivity": String(localized: "Productivity")
case "security": String(localized: "Security")
case "social": String(localized: "Social")
case "utilities": String(localized: "Utilities")
default: category
}
}
}

extension CatalogApp {
var displayDescription: String {
localizedDescription(preferredLanguages: Bundle.main.preferredLocalizations)
Expand Down
13 changes: 13 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ target_compile_options(SimStoreCatalogTest PRIVATE -parse-as-library)
add_test(NAME catalog COMMAND SimStoreCatalogTest)
set_tests_properties(catalog PROPERTIES TIMEOUT 10)

add_executable(SimStoreCatalogCategoriesCheck EXCLUDE_FROM_ALL CatalogCategoriesCheck.swift
"${PROJECT_SOURCE_DIR}/src/AppCatalog.swift"
"${PROJECT_SOURCE_DIR}/src/AppConfiguration.swift"
"${PROJECT_SOURCE_DIR}/src/CatalogCategory.swift"
)
target_compile_options(SimStoreCatalogCategoriesCheck PRIVATE -parse-as-library)
add_custom_target(CheckCatalogCategories
COMMAND "$<TARGET_FILE:SimStoreCatalogCategoriesCheck>"
DEPENDS SimStoreCatalogCategoriesCheck
COMMENT "Checking category coverage in the latest app catalog"
VERBATIM
)

add_executable(SimStoreCatalogLoadingTest CatalogLoadingTests.swift
"${PROJECT_SOURCE_DIR}/src/AppCatalog.swift"
"${PROJECT_SOURCE_DIR}/src/CatalogClient.swift"
Expand Down
47 changes: 47 additions & 0 deletions tests/CatalogCategoriesCheck.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Foundation

@main
struct CatalogCategoriesCheck {
static func main() async {
do {
let url = AppConfiguration.catalogURL
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData)
request.timeoutInterval = 30
let (data, response) = try await URLSession.shared.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw failure("Expected an HTTP response from \(url).")
}
guard response.statusCode == 200 else {
throw failure("The latest catalog returned HTTP \(response.statusCode).")
}
let catalog = try AppCatalog.decode(data)
var missing: [String: [String]] = [:]
for app in catalog.apps {
for category in app.categories where CatalogCategory(rawValue: category) == nil {
missing[category, default: []].append(app.id)
}
}
guard missing.isEmpty else {
let details = missing.keys.sorted().map { category in
" \(category): \(missing[category]!.sorted().joined(separator: ", "))"
}
throw failure(
"Unlisted catalog categories:\n\(details.joined(separator: "\n"))\nAdd them to CatalogCategory and translate their titles."
)
}
let categories = Set(catalog.apps.flatMap(\.categories))
print(
"PASS: all \(categories.count) categories across \(catalog.apps.count) apps in \(url) are declared."
)
} catch {
FileHandle.standardError.write(
Data("Catalog category check failed: \(error.localizedDescription)\n".utf8))
exit(EXIT_FAILURE)
}
}

private static func failure(_ message: String) -> NSError {
NSError(
domain: "CatalogCategoriesCheck", code: 1, userInfo: [NSLocalizedDescriptionKey: message])
}
}