Implemented the TemplateService service in the library target.
This commit is contained in:
parent
1de9738e6e
commit
a515747c21
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct FileService: FileServicing {
|
public struct FileService {
|
||||||
|
|
||||||
// MARK: Properties
|
// MARK: Properties
|
||||||
|
|
||||||
private let fileManager: FileManager
|
private let fileManager: FileManager
|
||||||
@ -12,6 +12,12 @@ public struct FileService: FileServicing {
|
|||||||
self.fileManager = fileManager
|
self.fileManager = fileManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - FileServicing
|
||||||
|
|
||||||
|
extension FileService: FileServicing {
|
||||||
|
|
||||||
// MARK: Computed
|
// MARK: Computed
|
||||||
|
|
||||||
public var currentFolder: URL {
|
public var currentFolder: URL {
|
||||||
|
50
Library/Sources/Public/Services/TemplateService.swift
Normal file
50
Library/Sources/Public/Services/TemplateService.swift
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import Foundation
|
||||||
|
import Mustache
|
||||||
|
|
||||||
|
public struct TemplateService {
|
||||||
|
|
||||||
|
// MARK: Properties
|
||||||
|
|
||||||
|
private let mustacheRenderer: MustacheLibrary
|
||||||
|
|
||||||
|
// MARK: Initialisers
|
||||||
|
|
||||||
|
public init(
|
||||||
|
bundle: Bundleable? = nil,
|
||||||
|
templateFolder: String
|
||||||
|
) async throws (TemplateServiceError) {
|
||||||
|
guard let pathResources = (bundle ?? Bundle.module).resourcePath else {
|
||||||
|
throw .resourcePathNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
let pathTemplates = pathResources + "/" + templateFolder
|
||||||
|
|
||||||
|
do {
|
||||||
|
self.mustacheRenderer = try await MustacheLibrary(directory: pathTemplates)
|
||||||
|
} catch {
|
||||||
|
throw .serviceNotInitialized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - TemplateServicing
|
||||||
|
|
||||||
|
extension TemplateService: TemplateServicing {
|
||||||
|
|
||||||
|
// MARK: Functions
|
||||||
|
|
||||||
|
public func render(_ object: Any, on template: String) async throws (TemplateServiceError) -> String {
|
||||||
|
guard mustacheRenderer.getTemplate(named: template) != nil else {
|
||||||
|
throw .templateNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let content = mustacheRenderer.render(object, withTemplate: template) else {
|
||||||
|
throw .contentNotRendered
|
||||||
|
}
|
||||||
|
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
import ColibriLibrary
|
||||||
|
import Foundation
|
||||||
|
import Testing
|
||||||
|
|
||||||
|
struct TemplateServiceTests {
|
||||||
|
|
||||||
|
// MARK: Properties
|
||||||
|
|
||||||
|
private let spy = TemplateServiceSpy()
|
||||||
|
|
||||||
|
// MARK: Functions tests
|
||||||
|
|
||||||
|
@Test(arguments: [String.content])
|
||||||
|
func render(_ content: String) async throws {
|
||||||
|
// GIVEN
|
||||||
|
let service = TemplateServiceMock(action: .render(content), spy: spy)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
let result = try await service.render([:], on: .template)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
#expect(result == content)
|
||||||
|
|
||||||
|
#expect(spy.actions.isEmpty == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(arguments: [TemplateServiceError.serviceNotInitialized, .resourcePathNotFound, .templateNotFound, .contentNotRendered])
|
||||||
|
func render(throws error: TemplateServiceError) async throws {
|
||||||
|
let service = TemplateServiceMock(action: .error(error), spy: spy)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
// THEN
|
||||||
|
await #expect(throws: error) {
|
||||||
|
try await service.render([:], on: .template)
|
||||||
|
}
|
||||||
|
|
||||||
|
#expect(spy.actions.isEmpty == true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - String+Constants
|
||||||
|
|
||||||
|
private extension String {
|
||||||
|
static let content = ""
|
||||||
|
static let template = ""
|
||||||
|
}
|
75
Test/Sources/Helpers/Mocks/TemplateServiceMock.swift
Normal file
75
Test/Sources/Helpers/Mocks/TemplateServiceMock.swift
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import ColibriLibrary
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
final class TemplateServiceMock {
|
||||||
|
|
||||||
|
// MARK: Properties
|
||||||
|
|
||||||
|
private var actions: [Action] = []
|
||||||
|
|
||||||
|
private weak var spy: TemplateServiceSpy?
|
||||||
|
|
||||||
|
// MARK: Initialisers
|
||||||
|
|
||||||
|
init(
|
||||||
|
action: Action,
|
||||||
|
spy: TemplateServiceSpy? = nil
|
||||||
|
) {
|
||||||
|
self.actions.append(action)
|
||||||
|
self.spy = spy
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - TemplateServicing
|
||||||
|
|
||||||
|
extension TemplateServiceMock: TemplateServicing {
|
||||||
|
|
||||||
|
// MARK: Functions
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
func render(_ object: Any, on template: String) async throws(TemplateServiceError) -> String {
|
||||||
|
guard let nextAction else { return .empty }
|
||||||
|
|
||||||
|
switch nextAction {
|
||||||
|
case .error(let error):
|
||||||
|
throw error
|
||||||
|
case .render(let content):
|
||||||
|
try await spy?.render(object, on: template)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers
|
||||||
|
|
||||||
|
private extension TemplateServiceMock {
|
||||||
|
|
||||||
|
// MARK: Computed
|
||||||
|
|
||||||
|
var nextAction: Action? {
|
||||||
|
guard !actions.isEmpty else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions.removeFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Actions
|
||||||
|
|
||||||
|
extension TemplateServiceMock {
|
||||||
|
enum Action {
|
||||||
|
case error(TemplateServiceError)
|
||||||
|
case render(String)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - String+Constants
|
||||||
|
|
||||||
|
private extension String {
|
||||||
|
static let empty = ""
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
|
import ColibriLibrary
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@testable import ColibriLibrary
|
|
||||||
|
|
||||||
final class FileServiceSpy {
|
final class FileServiceSpy {
|
||||||
|
|
||||||
// MARK: Properties
|
// MARK: Properties
|
||||||
|
38
Test/Sources/Helpers/Spies/TemplateServiceSpy.swift
Normal file
38
Test/Sources/Helpers/Spies/TemplateServiceSpy.swift
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import ColibriLibrary
|
||||||
|
|
||||||
|
final class TemplateServiceSpy {
|
||||||
|
|
||||||
|
// MARK: Properties
|
||||||
|
|
||||||
|
private(set) var actions: [Action] = []
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - TemplateServicing
|
||||||
|
|
||||||
|
extension TemplateServiceSpy: TemplateServicing {
|
||||||
|
|
||||||
|
// MARK: Functions
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
func render(_ object: Any, on template: String) async throws(TemplateServiceError) -> String {
|
||||||
|
actions.append(.rendered(object, template))
|
||||||
|
|
||||||
|
return .content
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Actions
|
||||||
|
|
||||||
|
extension TemplateServiceSpy {
|
||||||
|
enum Action {
|
||||||
|
case rendered(_ object: Any, _ template: String)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - String+Constants
|
||||||
|
|
||||||
|
private extension String {
|
||||||
|
static let content = ""
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user