From f214018e3a49146eed3fb6a11d5896e9b3e400b2 Mon Sep 17 00:00:00 2001 From: kNate Date: Sun, 26 Nov 2023 20:54:07 -0500 Subject: [PATCH] Wrap resources in namespaces --- .../BlackboardFramework/Assets/Asset.swift | 90 +++++++++++++++++++ .../Assets/AssetSetFactory.swift | 18 ++-- .../Color Assets/BlackboardColor.swift | 10 ++- .../BlackboardColorSwiftSource.swift | 28 +++--- .../Color Assets/ColorSet.swift | 6 +- .../Color Assets/ColorSetFactory.swift | 4 - .../Data Assets/BlackboardData.swift | 12 ++- .../BlackboardDataSwiftSource.swift | 6 +- .../Data Assets/DataSet.swift | 6 +- .../Data Assets/DataSetFactory.swift | 4 - .../Image Assets/BlackboardImage.swift | 12 ++- .../BlackboardImageSwiftSource.swift | 16 ++-- .../Image Assets/ImageSet.swift | 6 +- .../Image Assets/ImageSetFactory.swift | 4 - .../Main/BlackboardMain+Color.swift | 7 +- .../Main/BlackboardMain+DataAsset.swift | 5 +- .../Main/BlackboardMain+Image.swift | 7 +- .../Main/BlackboardMain+Nib.swift | 5 +- .../Main/BlackboardMain+Storyboard.swift | 5 +- .../Main/BlackboardMain.swift | 9 +- .../Source Code/Naming.swift | 27 ++++-- .../Source Code/SwiftSource.swift | 14 +++ .../BlackboardColorSwiftSourceTests.swift | 50 +++++------ .../Color Assets/BlackboardColorTests.swift | 70 +++++---------- .../Color Assets/ColorSetTests.swift | 60 ++++++------- .../BlackboardDataSwiftSourceTests.swift | 32 +++---- .../Data Assets/BlackboardDataTests.swift | 28 ++---- .../Data Assets/DataSetTests.swift | 24 ++--- .../BlackboardImageSwiftSourceTests.swift | 38 ++++---- .../Image Assets/BlackboardImageTests.swift | 49 +++------- .../Image Assets/ImageSetTests.swift | 42 ++++----- .../Source Code/NamingTests.swift | 11 +++ .../XCTest/Fixture.swift | 37 ++++---- 33 files changed, 414 insertions(+), 328 deletions(-) create mode 100644 Sources/BlackboardFramework/Assets/Asset.swift diff --git a/Sources/BlackboardFramework/Assets/Asset.swift b/Sources/BlackboardFramework/Assets/Asset.swift new file mode 100644 index 00000000..6dd22a6a --- /dev/null +++ b/Sources/BlackboardFramework/Assets/Asset.swift @@ -0,0 +1,90 @@ +// +// Copyright (c) 2024 Nathan E. Walczak +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +protocol Asset { + var namespace: String? { get } + var name: String { get } +} + +indirect enum AssetItem { + case asset(A) + case namespace(String, [AssetItem]) +} + +extension AssetItem: Comparable { + + static func < (lhs: AssetItem, rhs: AssetItem) -> Bool { + switch (lhs, rhs) { + case let (.asset(lhs), .asset(rhs)): + return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending + case let (.asset(lhs), .namespace(rhs, _)): + return lhs.name.localizedCaseInsensitiveCompare(rhs) == .orderedAscending + case let (.namespace(lhs, _), .asset(rhs)): + return lhs.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending + case let (.namespace(lhs, _), .namespace(rhs, _)): + return lhs.localizedCaseInsensitiveCompare(rhs) == .orderedAscending + } + } + + static func == (lhs: AssetItem, rhs: AssetItem) -> Bool { + switch (lhs, rhs) { + case let (.asset(lhs), .asset(rhs)): + return lhs.name == rhs.name + case let (.asset(lhs), .namespace(rhs, _)): + return lhs.name == rhs + case let (.namespace(lhs, _), .asset(rhs)): + return lhs == rhs.name + case let (.namespace(lhs, _), .namespace(rhs, _)): + return lhs == rhs + } + } + +} + +extension Collection { + func mapAssets(_ transform: @escaping (E) -> T) -> [AssetItem] where Element == AssetItem { + map { something in + switch something { + case let .asset(asset): + return .asset(transform(asset)) + case let .namespace(namespace, assets): + return .namespace(namespace, assets.mapAssets(transform)) + } + } + } + + func flatMapAssets() -> [E] where Element == AssetItem { + flatMap { something in + switch something { + case let .asset(asset): + return [asset] + case let .namespace(_, assets): + return assets.flatMapAssets() + } + } + + } +} diff --git a/Sources/BlackboardFramework/Assets/AssetSetFactory.swift b/Sources/BlackboardFramework/Assets/AssetSetFactory.swift index f84c8164..df977147 100644 --- a/Sources/BlackboardFramework/Assets/AssetSetFactory.swift +++ b/Sources/BlackboardFramework/Assets/AssetSetFactory.swift @@ -26,7 +26,7 @@ import Foundation protocol AssetSetFactory { - associatedtype AssetSet + associatedtype AssetSet: Asset var pathExtension: String { get } @@ -36,18 +36,22 @@ protocol AssetSetFactory { extension AssetSetFactory { - func assetsAt(path: String) -> [AssetSet] { + func assetItemsAt(paths: [String]) -> [AssetItem] { + paths.flatMap { assetsAt(path: $0) } + } + + func assetsAt(path: String) -> [AssetItem] { assetsAt(path: path, namespace: nil) } - func assetsAt(path: String, namespace: String?) -> [AssetSet] { + func assetsAt(path: String, namespace: String?) -> [AssetItem] { let fileManager = FileManager.default guard let contents = try? fileManager.contentsOfDirectory(atPath: path) else { return [] } - return contents.flatMap { content -> [AssetSet] in + return contents.flatMap { content -> [AssetItem] in let file = path.appendingPathComponent(content) guard fileManager.isDirectory(file) else { @@ -56,17 +60,19 @@ extension AssetSetFactory { if file.pathExtension == pathExtension { if let asset = assetAt(path: file, namespace: namespace) { - return [asset] + return [.asset(asset)] } return [] } if providesNamespaceAt(path: file) { let namespace = Naming.namespace(from: namespace, content) - return assetsAt(path: file, namespace: namespace) + let assets = assetsAt(path: file, namespace: namespace) + return assets.isEmpty ? [] : [.namespace(namespace, assets)] } return assetsAt(path: file, namespace: namespace) } + .sorted() } func assetAt(path: String, namespace: String?) -> AssetSet? { diff --git a/Sources/BlackboardFramework/Color Assets/BlackboardColor.swift b/Sources/BlackboardFramework/Color Assets/BlackboardColor.swift index f805bf18..441771ad 100644 --- a/Sources/BlackboardFramework/Color Assets/BlackboardColor.swift +++ b/Sources/BlackboardFramework/Color Assets/BlackboardColor.swift @@ -24,12 +24,14 @@ import Foundation -struct BlackboardColor { +struct BlackboardColor: Asset { var namespace: String? var name: String - var propertyName: String + var resourceName: String + var propertyName: String + var propertyPath: String } @@ -39,10 +41,12 @@ extension BlackboardColor { namespace = colorSet.namespace name = colorSet.name + resourceName = colorSet.resourceName + propertyName = Naming.methodName(from: colorSet.name) .removingSuffix("Color") - resourceName = Naming.namespace(from: colorSet.namespace, colorSet.name) ?? colorSet.name + propertyPath = Naming.propertyPath(namespace: namespace, propertyName: propertyName) } } diff --git a/Sources/BlackboardFramework/Color Assets/BlackboardColorSwiftSource.swift b/Sources/BlackboardFramework/Color Assets/BlackboardColorSwiftSource.swift index d8fd7c69..5919f823 100644 --- a/Sources/BlackboardFramework/Color Assets/BlackboardColorSwiftSource.swift +++ b/Sources/BlackboardFramework/Color Assets/BlackboardColorSwiftSource.swift @@ -28,14 +28,14 @@ extension SwiftSource { // MARK: Color Assets - func appendColorAssets(colors: [BlackboardColor]) -> Self { + func appendColorAssets(colors: [AssetItem]) -> Self { appendHeading(filename: Filename.ColorAsset, modules: ["Foundation"]) append("public struct ColorAsset: Hashable") { append("let name: String") } append() append("public extension ColorAsset") { - colors.forEach { color in + appendAssetItems(colors) { color in append("static let \(color.propertyName) = ColorAsset(name: \"\(color.resourceName)\")") } } @@ -46,7 +46,7 @@ extension SwiftSource { // MARK: Color - func appendColors(colors: [BlackboardColor], target: Version) -> Self { + func appendColors(colors: [AssetItem], target: Version) -> Self { appendHeading(filename: Filename.Color, modules: ["SwiftUI"], includeBundle: true) appendAvailability(.available(platform: .iOS, version: Version(13, 0)), target: target) append("public extension Color") { @@ -56,8 +56,8 @@ extension SwiftSource { } append() directive("#if swift(<5.9.0)") - colors.forEach { color in - append("static var \(color.propertyName): Color { Color(asset: .\(color.propertyName)) }") + appendAssetItems(colors) { color in + append("static var \(color.propertyName): Color { Color(asset: .\(color.propertyPath)) }") } directive("#endif") append() @@ -67,8 +67,10 @@ extension SwiftSource { appendAvailability(.available(platform: .iOS, version: Version(13, 0)), target: target) append("public extension ShapeStyle where Self == Color") { append() - colors.forEach { color in - append("static var \(color.propertyName): Color { Color(asset: .\(color.propertyName)) }") + colors.forEach { asset in + if case let .asset(color) = asset, color.namespace == nil { + append("static var \(color.propertyName): Color { Color(asset: .\(color.propertyPath)) }") + } } append() } @@ -80,15 +82,15 @@ extension SwiftSource { // MARK: CGColor - func appendCGColors(colors: [BlackboardColor]) -> Self { + func appendCGColors(colors: [AssetItem]) -> Self { appendHeading(filename: Filename.CGColor, modules: ["CoreGraphics"]) append("public extension ColorAsset") { append("var cgColor: CGColor { color.cgColor }") } append() append("public extension CGColor") { - colors.forEach { color in - append("static var \(color.propertyName): CGColor { ColorAsset.\(color.propertyName).cgColor }") + appendAssetItems(colors) { color in + append("static var \(color.propertyName): CGColor { ColorAsset.\(color.propertyPath).cgColor }") } } append() @@ -98,7 +100,7 @@ extension SwiftSource { // MARK: UIColor - func appendUIColors(colors: [BlackboardColor]) -> Self { + func appendUIColors(colors: [AssetItem]) -> Self { appendHeading(filename: Filename.UIColor, modules: ["UIKit"], includeBundle: true) append("public extension ColorAsset") { append("var color: UIColor { UIColor(asset: self) }") @@ -111,8 +113,8 @@ extension SwiftSource { } append() directive("#if swift(<5.9.0)") - colors.forEach { color in - append("static var \(color.propertyName): UIColor { UIColor(asset: .\(color.propertyName)) }") + appendAssetItems(colors) { color in + append("static var \(color.propertyName): UIColor { UIColor(asset: .\(color.propertyPath)) }") } directive("#endif") append() diff --git a/Sources/BlackboardFramework/Color Assets/ColorSet.swift b/Sources/BlackboardFramework/Color Assets/ColorSet.swift index e3e4a494..ff777410 100644 --- a/Sources/BlackboardFramework/Color Assets/ColorSet.swift +++ b/Sources/BlackboardFramework/Color Assets/ColorSet.swift @@ -24,9 +24,13 @@ import Foundation -struct ColorSet { +struct ColorSet: Asset { var namespace: String? var name: String + + var resourceName: String { + Naming.namespace(from: namespace, name) + } } extension ColorSet { diff --git a/Sources/BlackboardFramework/Color Assets/ColorSetFactory.swift b/Sources/BlackboardFramework/Color Assets/ColorSetFactory.swift index 05061215..19270b57 100644 --- a/Sources/BlackboardFramework/Color Assets/ColorSetFactory.swift +++ b/Sources/BlackboardFramework/Color Assets/ColorSetFactory.swift @@ -28,10 +28,6 @@ class ColorSetFactory: AssetSetFactory { let pathExtension = "colorset" - func colorSetsAt(paths: [String]) -> [ColorSet] { - paths.flatMap(assetsAt(path:)) - } - func asset(namespace: String?, name: String, data: Data) -> ColorSet? { guard let assetColorSet = try? JSONDecoder().decode(AssetColorSet.self, from: data) else { return nil diff --git a/Sources/BlackboardFramework/Data Assets/BlackboardData.swift b/Sources/BlackboardFramework/Data Assets/BlackboardData.swift index 037520b9..b010b3eb 100644 --- a/Sources/BlackboardFramework/Data Assets/BlackboardData.swift +++ b/Sources/BlackboardFramework/Data Assets/BlackboardData.swift @@ -24,13 +24,15 @@ import Foundation -struct BlackboardData { +struct BlackboardData: Asset { var namespace: String? var name: String - var propertyName: String - var resourceName: String + var resourceName: String + var propertyName: String + var propertyPath: String + } extension BlackboardData { @@ -39,10 +41,12 @@ extension BlackboardData { namespace = dataSet.namespace name = dataSet.name + resourceName = dataSet.resourceName + propertyName = Naming.methodName(from: dataSet.name) .removingSuffix("Data") - resourceName = Naming.namespace(from: dataSet.namespace, dataSet.name) ?? dataSet.name + propertyPath = Naming.propertyPath(namespace: namespace, propertyName: propertyName) } } diff --git a/Sources/BlackboardFramework/Data Assets/BlackboardDataSwiftSource.swift b/Sources/BlackboardFramework/Data Assets/BlackboardDataSwiftSource.swift index 1541dced..408a1ef5 100644 --- a/Sources/BlackboardFramework/Data Assets/BlackboardDataSwiftSource.swift +++ b/Sources/BlackboardFramework/Data Assets/BlackboardDataSwiftSource.swift @@ -28,14 +28,14 @@ extension SwiftSource { // MARK: Data Assets - func appendDataAssets(data: [BlackboardData]) -> Self { + func appendDataAssets(data: [AssetItem]) -> Self { appendHeading(filename: Filename.DataAsset, modules: ["Foundation"]) append("public struct DataAsset: Hashable") { append("let name: String") } append() append("public extension DataAsset") { - data.forEach { data in + appendAssetItems(data) { data in append("static let \(data.propertyName) = DataAsset(name: \"\(data.resourceName)\")") } } @@ -46,7 +46,7 @@ extension SwiftSource { // MARK: NSDataAsset - func appendNSDataAsset(data: [BlackboardData]) -> Self { + func appendNSDataAsset(data: [AssetItem]) -> Self { appendHeading(filename: Filename.NSDataAsset, modules: ["UIKit"], includeBundle: true) append("public extension DataAsset") { append("var dataAsset: NSDataAsset { NSDataAsset(asset: self) }") diff --git a/Sources/BlackboardFramework/Data Assets/DataSet.swift b/Sources/BlackboardFramework/Data Assets/DataSet.swift index 5509664a..18b7cdd2 100644 --- a/Sources/BlackboardFramework/Data Assets/DataSet.swift +++ b/Sources/BlackboardFramework/Data Assets/DataSet.swift @@ -24,9 +24,13 @@ import Foundation -struct DataSet { +struct DataSet: Asset { var namespace: String? var name: String + + var resourceName: String { + Naming.namespace(from: namespace, name) + } } extension DataSet { diff --git a/Sources/BlackboardFramework/Data Assets/DataSetFactory.swift b/Sources/BlackboardFramework/Data Assets/DataSetFactory.swift index 0c1899bc..1f29b130 100644 --- a/Sources/BlackboardFramework/Data Assets/DataSetFactory.swift +++ b/Sources/BlackboardFramework/Data Assets/DataSetFactory.swift @@ -28,10 +28,6 @@ class DataSetFactory: AssetSetFactory { let pathExtension = "dataset" - func dataSetsAt(paths: [String]) -> [DataSet] { - paths.flatMap(assetsAt(path:)) - } - func asset(namespace: String?, name: String, data: Data) -> DataSet? { guard let assetDataSet = try? JSONDecoder().decode(AssetDataSet.self, from: data) else { return nil diff --git a/Sources/BlackboardFramework/Image Assets/BlackboardImage.swift b/Sources/BlackboardFramework/Image Assets/BlackboardImage.swift index dbded0b1..9927ad91 100644 --- a/Sources/BlackboardFramework/Image Assets/BlackboardImage.swift +++ b/Sources/BlackboardFramework/Image Assets/BlackboardImage.swift @@ -24,13 +24,15 @@ import Foundation -struct BlackboardImage { +struct BlackboardImage: Asset { var namespace: String? var name: String - var propertyName: String - var resourceName: String + var resourceName: String + var propertyName: String + var propertyPath: String + } extension BlackboardImage { @@ -39,10 +41,12 @@ extension BlackboardImage { namespace = imageSet.namespace name = imageSet.name + resourceName = imageSet.resourceName + propertyName = Naming.methodName(from: imageSet.name) .removingSuffix("Image") - resourceName = Naming.namespace(from: imageSet.namespace, imageSet.name) ?? imageSet.name + propertyPath = Naming.propertyPath(namespace: namespace, propertyName: propertyName) } } diff --git a/Sources/BlackboardFramework/Image Assets/BlackboardImageSwiftSource.swift b/Sources/BlackboardFramework/Image Assets/BlackboardImageSwiftSource.swift index 9da4e61f..f347ba7f 100644 --- a/Sources/BlackboardFramework/Image Assets/BlackboardImageSwiftSource.swift +++ b/Sources/BlackboardFramework/Image Assets/BlackboardImageSwiftSource.swift @@ -28,14 +28,14 @@ extension SwiftSource { // MARK: Image Assets - func appendImageAssets(images: [BlackboardImage]) -> Self { + func appendImageAssets(images: [AssetItem]) -> Self { appendHeading(filename: Filename.ImageAsset, modules: ["Foundation"]) append("public struct ImageAsset: Hashable") { append("let name: String") } append() append("public extension ImageAsset") { - images.forEach { image in + appendAssetItems(images) { image in append("static let \(image.propertyName) = ImageAsset(name: \"\(image.resourceName)\")") } } @@ -46,7 +46,7 @@ extension SwiftSource { // MARK: Image - func appendImages(images: [BlackboardImage], target: Version, sdk: Version) -> Self { + func appendImages(images: [AssetItem], target: Version, sdk: Version) -> Self { appendHeading(filename: Filename.Image, modules: ["SwiftUI"], includeBundle: true) appendAvailability(.available(platform: .iOS, version: Version(13, 0)), target: target) append("public extension Image") { @@ -64,8 +64,8 @@ extension SwiftSource { } append() directive("#if swift(<5.9.0)") - images.forEach { image in - append("static var \(image.propertyName): Image { Image(asset: .\(image.propertyName)) }") + appendAssetItems(images) { image in + append("static var \(image.propertyName): Image { Image(asset: .\(image.propertyPath)) }") } directive("#endif") append() @@ -93,7 +93,7 @@ extension SwiftSource { // MARK: UIImage - func appendUIImages(images: [BlackboardImage]) -> Self { + func appendUIImages(images: [AssetItem]) -> Self { appendHeading(filename: Filename.UIImage, modules: ["UIKit"], includeBundle: true) append("public extension ImageAsset") { append("var image: UIImage { UIImage(asset: self) }") @@ -106,8 +106,8 @@ extension SwiftSource { } append() directive("#if swift(<5.9.0)") - images.forEach { image in - append("static var \(image.propertyName): UIImage { UIImage(asset: .\(image.propertyName)) }") + appendAssetItems(images) { image in + append("static var \(image.propertyName): UIImage { UIImage(asset: .\(image.propertyPath)) }") } directive("#endif") append() diff --git a/Sources/BlackboardFramework/Image Assets/ImageSet.swift b/Sources/BlackboardFramework/Image Assets/ImageSet.swift index 7763244d..db237082 100644 --- a/Sources/BlackboardFramework/Image Assets/ImageSet.swift +++ b/Sources/BlackboardFramework/Image Assets/ImageSet.swift @@ -24,9 +24,13 @@ import Foundation -struct ImageSet { +struct ImageSet: Asset { var namespace: String? var name: String + + var resourceName: String { + Naming.namespace(from: namespace, name) + } } extension ImageSet { diff --git a/Sources/BlackboardFramework/Image Assets/ImageSetFactory.swift b/Sources/BlackboardFramework/Image Assets/ImageSetFactory.swift index b3596eb1..b8ae8777 100644 --- a/Sources/BlackboardFramework/Image Assets/ImageSetFactory.swift +++ b/Sources/BlackboardFramework/Image Assets/ImageSetFactory.swift @@ -28,10 +28,6 @@ class ImageSetFactory: AssetSetFactory { let pathExtension = "imageset" - func imageSetsAt(paths: [String]) -> [ImageSet] { - paths.flatMap(assetsAt(path:)) - } - func asset(namespace: String?, name: String, data: Data) -> ImageSet? { guard let assetImageSet = try? JSONDecoder().decode(AssetImageSet.self, from: data) else { return nil diff --git a/Sources/BlackboardFramework/Main/BlackboardMain+Color.swift b/Sources/BlackboardFramework/Main/BlackboardMain+Color.swift index 2db9ac9d..2d44d8fc 100644 --- a/Sources/BlackboardFramework/Main/BlackboardMain+Color.swift +++ b/Sources/BlackboardFramework/Main/BlackboardMain+Color.swift @@ -26,13 +26,12 @@ import Foundation extension BlackboardMain { - func processColors(_ input: [String], _ output: String) -> [ColorSet] { + func processColors(_ input: [String], _ output: String) -> [AssetItem] { guard !skipColors else { return [] } - let colorSets = ColorSetFactory().colorSetsAt(paths: input) + let colorSets = ColorSetFactory().assetItemsAt(paths: input) - var blackboardColors = colorSets.compactMap(BlackboardColor.init) - blackboardColors.sort { $0.propertyName.localizedCaseInsensitiveCompare($1.propertyName) == .orderedAscending } + let blackboardColors = colorSets.mapAssets(BlackboardColor.init) guard !blackboardColors.isEmpty else { return [] diff --git a/Sources/BlackboardFramework/Main/BlackboardMain+DataAsset.swift b/Sources/BlackboardFramework/Main/BlackboardMain+DataAsset.swift index 7fb68637..e793fb42 100644 --- a/Sources/BlackboardFramework/Main/BlackboardMain+DataAsset.swift +++ b/Sources/BlackboardFramework/Main/BlackboardMain+DataAsset.swift @@ -29,10 +29,9 @@ extension BlackboardMain { func processDataAssets(_ input: [String], _ output: String) { guard !skipDataAssets else { return } - let dataSets = DataSetFactory().dataSetsAt(paths: input) + let dataSets = DataSetFactory().assetItemsAt(paths: input) - let blackboardData = dataSets.compactMap(BlackboardData.init) - .sorted { $0.propertyName.localizedCaseInsensitiveCompare($1.propertyName) == .orderedAscending } + let blackboardData = dataSets.mapAssets(BlackboardData.init) guard !blackboardData.isEmpty else { return diff --git a/Sources/BlackboardFramework/Main/BlackboardMain+Image.swift b/Sources/BlackboardFramework/Main/BlackboardMain+Image.swift index 6a3f95fc..572ccc4b 100644 --- a/Sources/BlackboardFramework/Main/BlackboardMain+Image.swift +++ b/Sources/BlackboardFramework/Main/BlackboardMain+Image.swift @@ -26,13 +26,12 @@ import Foundation extension BlackboardMain { - func processImages(_ input: [String], _ output: String) -> [ImageSet] { + func processImages(_ input: [String], _ output: String) -> [AssetItem] { guard !skipImages else { return [] } - let imageSets = ImageSetFactory().imageSetsAt(paths: input) + let imageSets = ImageSetFactory().assetItemsAt(paths: input) - let blackboardImages = imageSets.compactMap(BlackboardImage.init) - .sorted { $0.propertyName.localizedCaseInsensitiveCompare($1.propertyName) == .orderedAscending } + let blackboardImages = imageSets.mapAssets(BlackboardImage.init) guard !blackboardImages.isEmpty else { return [] diff --git a/Sources/BlackboardFramework/Main/BlackboardMain+Nib.swift b/Sources/BlackboardFramework/Main/BlackboardMain+Nib.swift index 5fe73201..34e1a512 100644 --- a/Sources/BlackboardFramework/Main/BlackboardMain+Nib.swift +++ b/Sources/BlackboardFramework/Main/BlackboardMain+Nib.swift @@ -26,14 +26,11 @@ import Foundation extension BlackboardMain { - func valiateNibs(_ input: [String], _ colorSets: [ColorSet], _ imageSets: [ImageSet]) { + func valiateNibs(_ input: [String], _ knownNamedColors: Set, _ knownNamedImages: Set) { guard !skipValidation && !skipNibValidation else { return } let nibs = Nib.nibsAt(paths: input) - let knownNamedColors = Set(colorSets.map(\.name)) - let knownNamedImages = Set(imageSets.map(\.name)) - nibs.forEach { nib in if !skipColors { Set(nib.namedColorResources) diff --git a/Sources/BlackboardFramework/Main/BlackboardMain+Storyboard.swift b/Sources/BlackboardFramework/Main/BlackboardMain+Storyboard.swift index 3e4201bd..c244881c 100644 --- a/Sources/BlackboardFramework/Main/BlackboardMain+Storyboard.swift +++ b/Sources/BlackboardFramework/Main/BlackboardMain+Storyboard.swift @@ -53,12 +53,9 @@ extension BlackboardMain { return storyboards } - func valiateStoryboards(_ storyboards: [Storyboard], _ colorSets: [ColorSet], _ imageSets: [ImageSet]) { + func valiateStoryboards(_ storyboards: [Storyboard], _ knownNamedColors: Set, _ knownNamedImages: Set) { guard !skipValidation && !skipStoryboardValidation else { return } - let knownNamedColors = Set(colorSets.map(\.name)) - let knownNamedImages = Set(imageSets.map(\.name)) - storyboards.forEach { storyboard in if !skipColors { Set(storyboard.namedColorResources) diff --git a/Sources/BlackboardFramework/Main/BlackboardMain.swift b/Sources/BlackboardFramework/Main/BlackboardMain.swift index 43b5edb4..c8d42d41 100644 --- a/Sources/BlackboardFramework/Main/BlackboardMain.swift +++ b/Sources/BlackboardFramework/Main/BlackboardMain.swift @@ -161,13 +161,18 @@ public struct BlackboardMain { let imageSets = processImages(input, output) let localizables = processLocalizable(input, output) + // Validate + + let knownNamedColors = Set(colorSets.flatMapAssets().map(\.resourceName)) + let knownNamedImages = Set(imageSets.flatMapAssets().map(\.resourceName)) + // Validate Storyboard Resources - valiateStoryboards(storyboards, colorSets, imageSets) + valiateStoryboards(storyboards, knownNamedColors, knownNamedImages) // Valiate Nib Resources - valiateNibs(input, colorSets, imageSets) + valiateNibs(input, knownNamedColors, knownNamedImages) // Validate Localizable Resources diff --git a/Sources/BlackboardFramework/Source Code/Naming.swift b/Sources/BlackboardFramework/Source Code/Naming.swift index b20b4c57..90b35be8 100644 --- a/Sources/BlackboardFramework/Source Code/Naming.swift +++ b/Sources/BlackboardFramework/Source Code/Naming.swift @@ -83,14 +83,25 @@ enum Naming { .joined() } - static func namespace(from namespaces: String?...) -> String? { - let namespaces = namespaces.compactMap { $0 } - - if namespaces.isEmpty { - return nil - } - - return namespaces.joined(separator: "/") + static func namespace(from namespaces: String?...) -> String { + namespaces + .compactMap { $0 } + .joined(separator: "/") } + static func lastNamespaceName(from namespace: String) -> String { + guard let lastNamespaceComponent = namespace.split(separator: "/").last else { return "" } + return Naming.name(from: String(lastNamespaceComponent)) + } + + static func propertyPath(namespace: String?, propertyName: String) -> String { + if let namespace = namespace { + let namespace = namespace + .split(separator: "/") + .map { Naming.name(from: String($0)) } + .joined(separator: ".") + return namespace + "." + propertyName + } + return propertyName + } } diff --git a/Sources/BlackboardFramework/Source Code/SwiftSource.swift b/Sources/BlackboardFramework/Source Code/SwiftSource.swift index cef21dfd..d8aae352 100644 --- a/Sources/BlackboardFramework/Source Code/SwiftSource.swift +++ b/Sources/BlackboardFramework/Source Code/SwiftSource.swift @@ -153,4 +153,18 @@ extension SwiftSource { } } + func appendAssetItems(_ assetItems: [AssetItem], block: (_ asset: Asset) -> Void) { + assetItems.forEach { asset in + switch asset { + case let .asset(asset): + block(asset) + case let .namespace(namespace, assets): + let namespace = Naming.lastNamespaceName(from: namespace) + append("enum \(namespace)") { + appendAssetItems(assets, block: block) + } + } + } + } + } diff --git a/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorSwiftSourceTests.swift b/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorSwiftSourceTests.swift index 5eb99fae..b0a49c60 100644 --- a/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorSwiftSourceTests.swift +++ b/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorSwiftSourceTests.swift @@ -28,34 +28,34 @@ import XCTest class BlackboardColorSwiftSourceTests: XCTestCase { - var blackboardColors: [BlackboardColor] { - let colorSets: [ColorSet?] = [ - Fixture.colorSet(project: .shared, path: "Dark", name: "Absolute Zero"), - Fixture.colorSet(project: .shared, name: "Bisque"), - Fixture.colorSet(project: .shared, path: "Dark", name: "Charcoal"), - Fixture.colorSet(project: .shared, path: "Dark", name: "dark-olive-green"), - Fixture.colorSet(project: .shared, name: "Desire"), - Fixture.colorSet(project: .shared, name: "Emerald"), - Fixture.colorSet(project: .shared, name: "Empty"), - Fixture.colorSet(project: .shared, path: "Dark", name: "firebrick-color"), - Fixture.colorSet(project: .shared, name: "Fluorescent/Blizzard Blue"), - Fixture.colorSet(project: .shared, name: "Fluorescent/Magic Mint"), - Fixture.colorSet(project: .shared, name: "Fluorescent/Radical Red"), - Fixture.colorSet(project: .shared, path: "Dark", name: "maroon color"), - Fixture.colorSet(project: .shared, path: "Dark", name: "Night") - ] - - var blackboardColors = colorSets - .compactMap { $0 } - .compactMap(BlackboardColor.init) - - blackboardColors.sort { $0.propertyName.localizedCaseInsensitiveCompare($1.propertyName) == .orderedAscending } - - return blackboardColors + var blackboardColors: [AssetItem] { + do { + let colorSets: [AssetItem] = [ + .asset(try Fixture.colorSet(project: .shared, path: "Dark", name: "Absolute Zero")), + .asset(try Fixture.colorSet(project: .shared, name: "Bisque")), + .asset(try Fixture.colorSet(project: .shared, path: "Dark", name: "Charcoal")), + .asset(try Fixture.colorSet(project: .shared, path: "Dark", name: "dark-olive-green")), + .asset(try Fixture.colorSet(project: .shared, name: "Desire")), + .asset(try Fixture.colorSet(project: .shared, name: "Emerald")), + .asset(try Fixture.colorSet(project: .shared, name: "Empty")), + .asset(try Fixture.colorSet(project: .shared, path: "Dark", name: "firebrick-color")), + .namespace("Fluorescent", [ + .asset(try Fixture.colorSet(project: .shared, namespace: "Fluorescent", name: "Radical Red")), + .asset(try Fixture.colorSet(project: .shared, namespace: "Fluorescent", name: "Blizzard Blue")), + .asset(try Fixture.colorSet(project: .shared, namespace: "Fluorescent", name: "Magic Mint")) + ].sorted()), + .asset(try Fixture.colorSet(project: .shared, path: "Dark", name: "maroon color")), + .asset(try Fixture.colorSet(project: .shared, path: "Dark", name: "Night")) + ].sorted() + + return colorSets.mapAssets(BlackboardColor.init) + } catch { + return [] + } } func testNumberOfColors() { - XCTAssertEqual(blackboardColors.count, 13) + XCTAssertEqual(blackboardColors.flatMapAssets().count, 13) } func testColorAssetSource() { diff --git a/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorTests.swift b/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorTests.swift index c358157b..89ed7139 100644 --- a/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorTests.swift +++ b/Tests/BlackboardFrameworkTests/Color Assets/BlackboardColorTests.swift @@ -28,11 +28,8 @@ import XCTest class BlackboardColorTests: XCTestCase { - func testAbsoluteZero() { - guard let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "Absolute Zero") else { - XCTFail("Unable to decode color set data") - return - } + func testAbsoluteZero() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "Absolute Zero") let blackboardColor = BlackboardColor(colorSet) @@ -40,11 +37,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "absoluteZero") } - func testBisque() { - guard let colorSet = Fixture.colorSet(project: .shared, name: "Bisque") else { - XCTFail("Unable to decode color set data") - return - } + func testBisque() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Bisque") let blackboardColor = BlackboardColor(colorSet) @@ -52,11 +46,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "bisque") } - func testCharcoal() { - guard let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "Charcoal") else { - XCTFail("Unable to decode color set data") - return - } + func testCharcoal() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "Charcoal") let blackboardColor = BlackboardColor(colorSet) @@ -64,11 +55,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "charcoal") } - func testDarkOliveGreen() { - guard let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "dark-olive-green") else { - XCTFail("Unable to decode color set data") - return - } + func testDarkOliveGreen() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "dark-olive-green") let blackboardColor = BlackboardColor(colorSet) @@ -76,11 +64,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "darkOliveGreen") } - func testDesire() { - guard let colorSet = Fixture.colorSet(project: .shared, name: "Desire") else { - XCTFail("Unable to decode color set data") - return - } + func testDesire() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Desire") let blackboardColor = BlackboardColor(colorSet) @@ -88,11 +73,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "desire") } - func testEmerald() { - guard let colorSet = Fixture.colorSet(project: .shared, name: "Emerald") else { - XCTFail("Unable to decode color set data") - return - } + func testEmerald() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Emerald") let blackboardColor = BlackboardColor(colorSet) @@ -100,11 +82,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "emerald") } - func testEmpty() { - guard let colorSet = Fixture.colorSet(project: .shared, name: "Empty") else { - XCTFail("Unable to decode color set data") - return - } + func testEmpty() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Empty") let blackboardColor = BlackboardColor(colorSet) @@ -112,11 +91,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "empty") } - func testFirebrick() { - guard let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "firebrick-color") else { - XCTFail("Unable to decode color set data") - return - } + func testFirebrick() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "firebrick-color") let blackboardColor = BlackboardColor(colorSet) @@ -124,11 +100,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "firebrick") } - func testMaroon() { - guard let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "maroon color") else { - XCTFail("Unable to decode color set data") - return - } + func testMaroon() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "maroon color") let blackboardColor = BlackboardColor(colorSet) @@ -136,11 +109,8 @@ class BlackboardColorTests: XCTestCase { XCTAssertEqual(blackboardColor.propertyName, "maroon") } - func testNight() { - guard let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "Night") else { - XCTFail("Unable to decode color set data") - return - } + func testNight() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "Night") let blackboardColor = BlackboardColor(colorSet) diff --git a/Tests/BlackboardFrameworkTests/Color Assets/ColorSetTests.swift b/Tests/BlackboardFrameworkTests/Color Assets/ColorSetTests.swift index 8a1523ef..ff4a64f8 100644 --- a/Tests/BlackboardFrameworkTests/Color Assets/ColorSetTests.swift +++ b/Tests/BlackboardFrameworkTests/Color Assets/ColorSetTests.swift @@ -28,64 +28,64 @@ import XCTest class ColorSetTests: XCTestCase { - func testAbsoluteZero() { - let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "Absolute Zero") + func testAbsoluteZero() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "Absolute Zero") - XCTAssertEqual(colorSet?.name, "Absolute Zero") + XCTAssertEqual(colorSet.name, "Absolute Zero") } - func testBisque() { - let colorSet = Fixture.colorSet(project: .shared, name: "Bisque") + func testBisque() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Bisque") - XCTAssertEqual(colorSet?.name, "Bisque") + XCTAssertEqual(colorSet.name, "Bisque") } - func testCharcoal() { - let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "Charcoal") + func testCharcoal() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "Charcoal") - XCTAssertEqual(colorSet?.name, "Charcoal") + XCTAssertEqual(colorSet.name, "Charcoal") } - func testDarkOliveGreen() { - let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "dark-olive-green") + func testDarkOliveGreen() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "dark-olive-green") - XCTAssertEqual(colorSet?.name, "dark-olive-green") + XCTAssertEqual(colorSet.name, "dark-olive-green") } - func testDesire() { - let colorSet = Fixture.colorSet(project: .shared, name: "Desire") + func testDesire() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Desire") - XCTAssertEqual(colorSet?.name, "Desire") + XCTAssertEqual(colorSet.name, "Desire") } - func testEmerald() { - let colorSet = Fixture.colorSet(project: .shared, name: "Emerald") + func testEmerald() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Emerald") - XCTAssertEqual(colorSet?.name, "Emerald") + XCTAssertEqual(colorSet.name, "Emerald") } - func testEmpty() { - let colorSet = Fixture.colorSet(project: .shared, name: "Empty") + func testEmpty() throws { + let colorSet = try Fixture.colorSet(project: .shared, name: "Empty") - XCTAssertEqual(colorSet?.name, "Empty") + XCTAssertEqual(colorSet.name, "Empty") } - func testFirebrick() { - let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "firebrick-color") + func testFirebrick() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "firebrick-color") - XCTAssertEqual(colorSet?.name, "firebrick-color") + XCTAssertEqual(colorSet.name, "firebrick-color") } - func testMaroon() { - let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "maroon color") + func testMaroon() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "maroon color") - XCTAssertEqual(colorSet?.name, "maroon color") + XCTAssertEqual(colorSet.name, "maroon color") } - func testNight() { - let colorSet = Fixture.colorSet(project: .shared, path: "Dark", name: "Night") + func testNight() throws { + let colorSet = try Fixture.colorSet(project: .shared, path: "Dark", name: "Night") - XCTAssertEqual(colorSet?.name, "Night") + XCTAssertEqual(colorSet.name, "Night") } } diff --git a/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataSwiftSourceTests.swift b/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataSwiftSourceTests.swift index 7470301b..ad5ff27e 100644 --- a/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataSwiftSourceTests.swift +++ b/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataSwiftSourceTests.swift @@ -28,25 +28,25 @@ import XCTest class BlackboardDataSwiftSourceTests: XCTestCase { - var blackboardData: [BlackboardData] { - let dataSets: [DataSet?] = [ - Fixture.dataSet(project: .shared, name: "Level/N001"), - Fixture.dataSet(project: .shared, name: "Level/N002"), - Fixture.dataSet(project: .shared, name: "Names"), - Fixture.dataSet(project: .shared, name: "Welcome Message") - ] - - var blackboardData = dataSets - .compactMap { $0 } - .compactMap(BlackboardData.init) - - blackboardData.sort { $0.propertyName.localizedCaseInsensitiveCompare($1.propertyName) == .orderedAscending } - - return blackboardData + var blackboardData: [AssetItem] { + do { + let dataSets: [AssetItem] = [ + .namespace("Level", [ + .asset(try Fixture.dataSet(project: .shared, namespace: "Level", name: "N002")), + .asset(try Fixture.dataSet(project: .shared, namespace: "Level", name: "N001")) + ].sorted()), + .asset(try Fixture.dataSet(project: .shared, name: "Welcome Message")), + .asset(try Fixture.dataSet(project: .shared, name: "Names")) + ].sorted() + + return dataSets.mapAssets(BlackboardData.init) + } catch { + return [] + } } func testNumberOfData() { - XCTAssertEqual(blackboardData.count, 4) + XCTAssertEqual(blackboardData.flatMapAssets().count, 4) } func testDataAssetSource() { diff --git a/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataTests.swift b/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataTests.swift index 1b90d739..f1798be2 100644 --- a/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataTests.swift +++ b/Tests/BlackboardFrameworkTests/Data Assets/BlackboardDataTests.swift @@ -28,11 +28,8 @@ import XCTest class BlackboardDataTests: XCTestCase { - func testLevel001() { - guard let dataSet = Fixture.dataSet(project: .shared, name: "Level/N001") else { - XCTFail("Unable to decode image set data") - return - } + func testLevel001() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Level/N001") let blackboardData = BlackboardData(dataSet) @@ -40,11 +37,8 @@ class BlackboardDataTests: XCTestCase { XCTAssertEqual(blackboardData.propertyName, "levelN001") } - func testLevel002() { - guard let dataSet = Fixture.dataSet(project: .shared, name: "Level/N002") else { - XCTFail("Unable to decode image set data") - return - } + func testLevel002() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Level/N002") let blackboardData = BlackboardData(dataSet) @@ -52,11 +46,8 @@ class BlackboardDataTests: XCTestCase { XCTAssertEqual(blackboardData.propertyName, "levelN002") } - func testNames() { - guard let dataSet = Fixture.dataSet(project: .shared, name: "Names") else { - XCTFail("Unable to decode image set data") - return - } + func testNames() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Names") let blackboardData = BlackboardData(dataSet) @@ -64,11 +55,8 @@ class BlackboardDataTests: XCTestCase { XCTAssertEqual(blackboardData.propertyName, "names") } - func testWelcomeMessage() { - guard let dataSet = Fixture.dataSet(project: .shared, name: "Welcome Message") else { - XCTFail("Unable to decode image set data") - return - } + func testWelcomeMessage() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Welcome Message") let blackboardData = BlackboardData(dataSet) diff --git a/Tests/BlackboardFrameworkTests/Data Assets/DataSetTests.swift b/Tests/BlackboardFrameworkTests/Data Assets/DataSetTests.swift index 5b48ac5d..364dcb81 100644 --- a/Tests/BlackboardFrameworkTests/Data Assets/DataSetTests.swift +++ b/Tests/BlackboardFrameworkTests/Data Assets/DataSetTests.swift @@ -28,28 +28,28 @@ import XCTest class DataSetTests: XCTestCase { - func testLevel001() { - let dataSet = Fixture.dataSet(project: .shared, name: "Level/N001") + func testLevel001() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Level/N001") - XCTAssertEqual(dataSet?.name, "Level/N001") + XCTAssertEqual(dataSet.name, "Level/N001") } - func testLevel002() { - let dataSet = Fixture.dataSet(project: .shared, name: "Level/N002") + func testLevel002() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Level/N002") - XCTAssertEqual(dataSet?.name, "Level/N002") + XCTAssertEqual(dataSet.name, "Level/N002") } - func testNames() { - let dataSet = Fixture.dataSet(project: .shared, name: "Names") + func testNames() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Names") - XCTAssertEqual(dataSet?.name, "Names") + XCTAssertEqual(dataSet.name, "Names") } - func testWelcomeMessage() { - let dataSet = Fixture.dataSet(project: .shared, name: "Welcome Message") + func testWelcomeMessage() throws { + let dataSet = try Fixture.dataSet(project: .shared, name: "Welcome Message") - XCTAssertEqual(dataSet?.name, "Welcome Message") + XCTAssertEqual(dataSet.name, "Welcome Message") } } diff --git a/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageSwiftSourceTests.swift b/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageSwiftSourceTests.swift index b39aa74f..47840e90 100644 --- a/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageSwiftSourceTests.swift +++ b/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageSwiftSourceTests.swift @@ -28,28 +28,28 @@ import XCTest class BlackboardImageSwiftSourceTests: XCTestCase { - var blackboardImages: [BlackboardImage] { - let imageSets: [ImageSet?] = [ - Fixture.imageSet(project: .shared, name: "button"), - Fixture.imageSet(project: .shared, path: "Paper Clips", name: "green-paper-clip"), - Fixture.imageSet(project: .shared, name: "green-pencil"), - Fixture.imageSet(project: .shared, name: "Red/cup"), - Fixture.imageSet(project: .shared, name: "Red/stapler"), - Fixture.imageSet(project: .shared, path: "Paper Clips", name: "silver-paper-clip"), - Fixture.imageSet(project: .shared, name: "white-dice") - ] - - var blackboardImages = imageSets - .compactMap { $0 } - .compactMap(BlackboardImage.init) - - blackboardImages.sort { $0.propertyName.localizedCaseInsensitiveCompare($1.propertyName) == .orderedAscending } - - return blackboardImages + var blackboardImages: [AssetItem] { + do { + let imageSets: [AssetItem] = [ + .asset(try Fixture.imageSet(project: .shared, name: "button")), + .asset(try Fixture.imageSet(project: .shared, path: "Paper Clips", name: "green-paper-clip")), + .asset(try Fixture.imageSet(project: .shared, name: "green-pencil")), + .namespace("Red", [ + .asset(try Fixture.imageSet(project: .shared, namespace: "Red", name: "stapler")), + .asset(try Fixture.imageSet(project: .shared, namespace: "Red", name: "cup")) + ].sorted()), + .asset(try Fixture.imageSet(project: .shared, path: "Paper Clips", name: "silver-paper-clip")), + .asset(try Fixture.imageSet(project: .shared, name: "white-dice")) + ].sorted() + + return imageSets.mapAssets(BlackboardImage.init) + } catch { + return [] + } } func testNumberOfImages() { - XCTAssertEqual(blackboardImages.count, 7) + XCTAssertEqual(blackboardImages.flatMapAssets().count, 7) } func testImageAssetSource() { diff --git a/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageTests.swift b/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageTests.swift index 4a4d78d3..e58bf7da 100644 --- a/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageTests.swift +++ b/Tests/BlackboardFrameworkTests/Image Assets/BlackboardImageTests.swift @@ -28,11 +28,8 @@ import XCTest class BlackboardImageTests: XCTestCase { - func testButton() { - guard let imageSet = Fixture.imageSet(project: .shared, name: "button") else { - XCTFail("Unable to decode image set data") - return - } + func testButton() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "button") let blackboardImage = BlackboardImage(imageSet) @@ -40,11 +37,8 @@ class BlackboardImageTests: XCTestCase { XCTAssertEqual(blackboardImage.propertyName, "button") } - func testGreenPaperClip() { - guard let imageSet = Fixture.imageSet(project: .shared, path: "Paper Clips", name: "green-paper-clip") else { - XCTFail("Unable to decode image set data") - return - } + func testGreenPaperClip() throws { + let imageSet = try Fixture.imageSet(project: .shared, path: "Paper Clips", name: "green-paper-clip") let blackboardImage = BlackboardImage(imageSet) @@ -52,11 +46,8 @@ class BlackboardImageTests: XCTestCase { XCTAssertEqual(blackboardImage.propertyName, "greenPaperClip") } - func testGreenPencil() { - guard let imageSet = Fixture.imageSet(project: .shared, name: "green-pencil") else { - XCTFail("Unable to decode image set data") - return - } + func testGreenPencil() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "green-pencil") let blackboardImage = BlackboardImage(imageSet) @@ -64,11 +55,8 @@ class BlackboardImageTests: XCTestCase { XCTAssertEqual(blackboardImage.propertyName, "greenPencil") } - func testRedCup() { - guard let imageSet = Fixture.imageSet(project: .shared, name: "Red/cup") else { - XCTFail("Unable to decode image set data") - return - } + func testRedCup() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "Red/cup") let blackboardImage = BlackboardImage(imageSet) @@ -76,11 +64,8 @@ class BlackboardImageTests: XCTestCase { XCTAssertEqual(blackboardImage.propertyName, "redCup") } - func testRedStapler() { - guard let imageSet = Fixture.imageSet(project: .shared, name: "Red/stapler") else { - XCTFail("Unable to decode image set data") - return - } + func testRedStapler() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "Red/stapler") let blackboardImage = BlackboardImage(imageSet) @@ -88,11 +73,8 @@ class BlackboardImageTests: XCTestCase { XCTAssertEqual(blackboardImage.propertyName, "redStapler") } - func testSilverPaperClip() { - guard let imageSet = Fixture.imageSet(project: .shared, path: "Paper Clips", name: "silver-paper-clip") else { - XCTFail("Unable to decode image set data") - return - } + func testSilverPaperClip() throws { + let imageSet = try Fixture.imageSet(project: .shared, path: "Paper Clips", name: "silver-paper-clip") let blackboardImage = BlackboardImage(imageSet) @@ -100,11 +82,8 @@ class BlackboardImageTests: XCTestCase { XCTAssertEqual(blackboardImage.propertyName, "silverPaperClip") } - func testWhiteDice() { - guard let imageSet = Fixture.imageSet(project: .shared, name: "white-dice") else { - XCTFail("Unable to decode image set data") - return - } + func testWhiteDice() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "white-dice") let blackboardImage = BlackboardImage(imageSet) diff --git a/Tests/BlackboardFrameworkTests/Image Assets/ImageSetTests.swift b/Tests/BlackboardFrameworkTests/Image Assets/ImageSetTests.swift index 75cd85e4..ae8d52d4 100644 --- a/Tests/BlackboardFrameworkTests/Image Assets/ImageSetTests.swift +++ b/Tests/BlackboardFrameworkTests/Image Assets/ImageSetTests.swift @@ -28,46 +28,46 @@ import XCTest class ImageSetTests: XCTestCase { - func testButton() { - let imageSet = Fixture.imageSet(project: .shared, name: "button") + func testButton() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "button") - XCTAssertEqual(imageSet?.name, "button") + XCTAssertEqual(imageSet.name, "button") } - func testGreenPaperClip() { - let imageSet = Fixture.imageSet(project: .shared, path: "Paper Clips", name: "green-paper-clip") + func testGreenPaperClip() throws { + let imageSet = try Fixture.imageSet(project: .shared, path: "Paper Clips", name: "green-paper-clip") - XCTAssertEqual(imageSet?.name, "green-paper-clip") + XCTAssertEqual(imageSet.name, "green-paper-clip") } - func testGreenPencil() { - let imageSet = Fixture.imageSet(project: .shared, name: "green-pencil") + func testGreenPencil() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "green-pencil") - XCTAssertEqual(imageSet?.name, "green-pencil") + XCTAssertEqual(imageSet.name, "green-pencil") } - func testRedCup() { - let imageSet = Fixture.imageSet(project: .shared, name: "Red/cup") + func testRedCup() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "Red/cup") - XCTAssertEqual(imageSet?.name, "Red/cup") + XCTAssertEqual(imageSet.name, "Red/cup") } - func testRedStapler() { - let imageSet = Fixture.imageSet(project: .shared, name: "Red/stapler") + func testRedStapler() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "Red/stapler") - XCTAssertEqual(imageSet?.name, "Red/stapler") + XCTAssertEqual(imageSet.name, "Red/stapler") } - func testSilverPaperClip() { - let imageSet = Fixture.imageSet(project: .shared, path: "Paper Clips", name: "silver-paper-clip") + func testSilverPaperClip() throws { + let imageSet = try Fixture.imageSet(project: .shared, path: "Paper Clips", name: "silver-paper-clip") - XCTAssertEqual(imageSet?.name, "silver-paper-clip") + XCTAssertEqual(imageSet.name, "silver-paper-clip") } - func testWhiteDice() { - let imageSet = Fixture.imageSet(project: .shared, name: "white-dice") + func testWhiteDice() throws { + let imageSet = try Fixture.imageSet(project: .shared, name: "white-dice") - XCTAssertEqual(imageSet?.name, "white-dice") + XCTAssertEqual(imageSet.name, "white-dice") } } diff --git a/Tests/BlackboardFrameworkTests/Source Code/NamingTests.swift b/Tests/BlackboardFrameworkTests/Source Code/NamingTests.swift index c5665ecd..463e864d 100644 --- a/Tests/BlackboardFrameworkTests/Source Code/NamingTests.swift +++ b/Tests/BlackboardFrameworkTests/Source Code/NamingTests.swift @@ -70,6 +70,17 @@ class NamingTests: XCTestCase { XCTAssertEqual(Naming.namespace(from: "Fluorescent", "Radical Red"), "Fluorescent/Radical Red") } + func testLastNamespaceName() { + XCTAssertEqual(Naming.lastNamespaceName(from: "Fluorescent/Radical Red"), "RadicalRed") + XCTAssertEqual(Naming.lastNamespaceName(from: "One/Two/Three/Blue"), "Blue") + } + + func testPropertyPath() { + XCTAssertEqual(Naming.propertyPath(namespace: nil, propertyName: "absoluteZero"), "absoluteZero") + XCTAssertEqual(Naming.propertyPath(namespace: "Fluorescent", propertyName: "radicalRed"), "Fluorescent.radicalRed") + XCTAssertEqual(Naming.propertyPath(namespace: "Alpha/beta", propertyName: "darkRed"), "Alpha.Beta.darkRed") + } + func testSymbolCaseName() { XCTAssertEqual(Naming.methodName(from: "14.square.fill"), "number14SquareFill") XCTAssertEqual(Naming.methodName(from: "case"), "case") diff --git a/Tests/BlackboardFrameworkTests/XCTest/Fixture.swift b/Tests/BlackboardFrameworkTests/XCTest/Fixture.swift index 40f45603..3338a5c6 100644 --- a/Tests/BlackboardFrameworkTests/XCTest/Fixture.swift +++ b/Tests/BlackboardFrameworkTests/XCTest/Fixture.swift @@ -25,6 +25,10 @@ import XCTest @testable import BlackboardFramework +enum FixtureError: Error { + case missingResource +} + class Fixture { enum Project { @@ -51,34 +55,37 @@ class Fixture { return String(data: data, encoding: .utf8) } - static func colorSet(project: Project, path: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) -> ColorSet? { - let path = "\(project.path)/Resources/Colors.xcassets/\(path ?? ".")/\(name).colorset/Contents.json" + static func colorSet(project: Project, path: String? = nil, namespace: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) throws -> ColorSet { + let path = "\(project.path)/Resources/Colors.xcassets/\(path ?? ".")/\(namespace ?? "")/\(name).colorset/Contents.json" - guard let data = fixture(path, file: file, line: line) else { - return nil + if let data = fixture(path, file: file, line: line), + let colorSet = ColorSetFactory().asset(namespace: namespace, name: name, data: data) { + return colorSet } - return ColorSetFactory().asset(namespace: nil, name: name, data: data) + throw FixtureError.missingResource } - static func dataSet(project: Project, path: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) -> DataSet? { - let path = "\(project.path)/Resources/Data.xcassets/\(path ?? ".")/\(name).dataset/Contents.json" + static func dataSet(project: Project, path: String? = nil, namespace: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) throws-> DataSet { + let path = "\(project.path)/Resources/Data.xcassets/\(path ?? ".")/\(namespace ?? "")/\(name).dataset/Contents.json" - guard let data = fixture(path, file: file, line: line) else { - return nil + if let data = fixture(path, file: file, line: line), + let dataSet = DataSetFactory().asset(namespace: namespace, name: name, data: data){ + return dataSet } - return DataSetFactory().asset(namespace: nil, name: name, data: data) + throw FixtureError.missingResource } - static func imageSet(project: Project, path: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) -> ImageSet? { - let path = "\(project.path)/Resources/Images.xcassets/\(path ?? ".")/\(name).imageset/Contents.json" + static func imageSet(project: Project, path: String? = nil, namespace: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) throws-> ImageSet { + let path = "\(project.path)/Resources/Images.xcassets/\(path ?? ".")/\(namespace ?? "")/\(name).imageset/Contents.json" - guard let data = fixture(path, file: file, line: line) else { - return nil + if let data = fixture(path, file: file, line: line), + let imageSet = ImageSetFactory().asset(namespace: namespace, name: name, data: data) { + return imageSet } - return ImageSetFactory().asset(namespace: nil, name: name, data: data) + throw FixtureError.missingResource } static func storyboard(project: Project, path: String? = nil, name: String, file: StaticString = #file, line: UInt = #line) -> Storyboard? {