Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve preview API #1

Merged
merged 16 commits into from
Mar 8, 2024
13 changes: 13 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# These are supported funding model platforms

github: [0xLeif]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
40 changes: 40 additions & 0 deletions .github/workflows/docc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: docc
on:
release:
types: [released]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
pages:
environment:
name: github-pages
url: '${{ steps.deployment.outputs.page_url }}'
runs-on: macos-13
steps:
- uses: swift-actions/setup-swift@v1
- name: git checkout
uses: actions/checkout@v3
- name: docbuild
run: >
sudo xcode-select -s /Applications/Xcode_15.0.app;
xcodebuild docbuild -scheme AppDependency \
-derivedDataPath /tmp/docbuild \
-destination 'generic/platform=iOS';
$(xcrun --find docc) process-archive \
transform-for-static-hosting /tmp/docbuild/Build/Products/Debug-iphoneos/AppDependency.doccarchive \
--output-path docs \
--hosting-base-path 'AppDependency';
echo "<script>window.location.href +=
\"/documentation/appdependency\"</script>" > docs/index.html;
- name: artifacts
uses: actions/upload-pages-artifact@v1
with:
path: docs
- name: deploy
id: deployment
uses: actions/deploy-pages@v1
23 changes: 23 additions & 0 deletions .github/workflows/macOS.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This workflow will build a Swift project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift

name: macOS

on:
push:
branches: ["**"]

jobs:
build:
runs-on: macos-13

steps:
- uses: swift-actions/setup-swift@v1
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- uses: actions/checkout@v3
- name: Build for release
run: swift build -v -c release
- name: Test
run: swift test -v
20 changes: 20 additions & 0 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# This workflow will build a Swift project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift

name: Ubuntu

on:
push:
branches: ["**"]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: swift-actions/setup-swift@v1
- uses: actions/checkout@v3
- name: Build for release
run: swift build -v -c release
- name: Test
run: swift test -v
18 changes: 18 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Windows

on:
push:
branches: ["**"]

jobs:
build:
runs-on: windows-latest
steps:
- uses: compnerd/gha-setup-swift@main
with:
branch: swift-5.9.2-release
tag: 5.9.2-RELEASE

- uses: actions/checkout@v2
- run: swift build
- run: swift test
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.swiftpm/
xcworkspacedata
.netrc
Package.resolved

This file was deleted.

14 changes: 0 additions & 14 deletions Package.resolved

This file was deleted.

27 changes: 27 additions & 0 deletions Sources/AppDependency/Application/Application+public.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Foundation
#if !os(Linux) && !os(Windows)
import SwiftUI
#endif

// MARK: Application Functions

Expand Down Expand Up @@ -259,6 +262,30 @@ public extension Application {
}
}

#if !os(Linux) && !os(Windows)
// MARK: - SwiftUI Preview Dependency Functions

public extension Application {
/**
Use in SwiftUI previews to inject mock dependencies into the content view.
- Parameters:
- dependencyOverrides: An array of `Application.override(_, with:)` outputs that you want to use for the preview.
- content: A closure that returns the View you want to preview.
- Returns: A View with the overridden dependencies applied.
*/
@ViewBuilder
static func preview<Content: View>(
_ dependencyOverrides: DependencyOverride...,
content: @escaping () -> Content
) -> some View {
ApplicationPreview(
dependencyOverrides: dependencyOverrides,
content: content
)
}
}
#endif

// MARK: - DependencySlice Functions

extension Application {
Expand Down
34 changes: 34 additions & 0 deletions Sources/AppDependency/Application/Helper/ApplicationLogger.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#if os(Linux) || os(Windows)
/// `ApplicationLogger` is a class that provides logging functionalities for Linux and Windows operating systems.
open class ApplicationLogger {
/// Prints a debug message.
/// - Parameter message: The message to be logged.
open func debug(_ message: String) {
debug { message }
}

/// Prints a debug message.
/// - Parameter message: A closure that returns the message to be logged.
open func debug(_ message: () -> String) {
print(message())
}

/// Logs an error message.
/// - Parameters:
/// - error: The error that occurred.
/// - message: An optional custom message to accompany the error.
open func error(_ error: Error, message: String? = nil) {
guard let message else {
return print("Error: \(error.localizedDescription)")
}

print("\(message) (Error: \(error.localizedDescription))")
}

/// Logs an error message.
/// - Parameter message: The error message to be logged.
open func error(_ message: String) {
print("Error: \(message)")
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#if !os(Linux) && !os(Windows)
import SwiftUI

extension Application {
struct ApplicationPreview<Content: View>: View {
let dependencyOverrides: [DependencyOverride]
let content: () -> Content

init(
dependencyOverrides: [DependencyOverride],
content: @escaping () -> Content
) {
self.dependencyOverrides = dependencyOverrides
self.content = content
}

var body: some View {
content()
}
}
}
#endif
79 changes: 74 additions & 5 deletions Tests/AppDependencyTests/AppDependencyTests.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,81 @@
import XCTest
@testable import AppDependency

fileprivate protocol Networking {
func fetch()
}

fileprivate class NetworkService: Networking {
func fetch() {
fatalError()
}
}

fileprivate class MockNetworking: Networking {
func fetch() { /* no-op */ }
}

fileprivate class ComposableService {
let networking: Networking

init(networking: Networking) {
self.networking = networking
}
}

fileprivate extension Application {
var networking: Dependency<Networking> {
dependency(NetworkService())
}

var composableService: Dependency<ComposableService> {
dependency(ComposableService(networking: Application.dependency(\.networking)))
}
}

fileprivate struct ExampleDependencyWrapper {
@AppDependency(\.networking) private var networking

func fetch() {
networking.fetch()
}
}

final class AppDependencyTests: XCTestCase {
func testExample() throws {
// XCTest Documentation
// https://developer.apple.com/documentation/xctest
override class func setUp() {
Application.logging(isEnabled: true)
}

override class func tearDown() {
Application.logger.debug("AppDependencyTests \(Application.description)")
}

func testComposableDependencies() {
let dependencyOverride = Application.override(\.networking, with: MockNetworking())

let composableService = Application.dependency(\.composableService)
composableService.networking.fetch()

dependencyOverride.cancel()
}

func testDependency() async throws {
let networkingOverride = Application.override(\.networking, with: MockNetworking())

let mockNetworking = Application.dependency(\.networking)

XCTAssertNotNil(mockNetworking as? MockNetworking)

mockNetworking.fetch()

let example = ExampleDependencyWrapper()

example.fetch()

networkingOverride.cancel()

let networkingService = Application.dependency(\.networking)

// Defining Test Cases and Test Methods
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
XCTAssertNotNil(networkingService as? NetworkService)
}
}
Loading
Loading