mirror of
https://github.com/otaviocc/Triton.git
synced 2026-01-30 04:04:27 +00:00
Add SwiftLint
This commit is contained in:
parent
d3b596c26f
commit
ee174ab836
66 changed files with 395 additions and 213 deletions
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
|
@ -2,9 +2,7 @@ name: Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches: [ main ]
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
|
||||||
11
.github/workflows/swiftformat.yml
vendored
11
.github/workflows/swiftformat.yml
vendored
|
|
@ -2,9 +2,7 @@ name: SwiftFormat Check
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches: [ main ]
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
swiftformat:
|
swiftformat:
|
||||||
|
|
@ -19,9 +17,4 @@ jobs:
|
||||||
run: brew install swiftformat
|
run: brew install swiftformat
|
||||||
|
|
||||||
- name: Check code formatting
|
- name: Check code formatting
|
||||||
run: |
|
run: swiftformat --lint .
|
||||||
swiftformat --lint .
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "❌ Code formatting issues detected. Please run 'swiftformat .' locally to fix."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
|
||||||
20
.github/workflows/swiftlint.yml
vendored
Normal file
20
.github/workflows/swiftlint.yml
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
name: SwiftLint Check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
swiftlint:
|
||||||
|
name: SwiftLint
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install SwiftLint
|
||||||
|
run: brew install swiftlint
|
||||||
|
|
||||||
|
- name: Run SwiftLint
|
||||||
|
run: swiftlint lint --reporter github-actions-logging
|
||||||
4
.github/workflows/unit-tests.yml
vendored
4
.github/workflows/unit-tests.yml
vendored
|
|
@ -2,9 +2,7 @@ name: Unit Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches: [ main ]
|
||||||
- main
|
|
||||||
- develop
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
|
|
||||||
64
.swiftlint.yml
Normal file
64
.swiftlint.yml
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Minimal SwiftLint configuration
|
||||||
|
# SwiftFormat handles all formatting, so SwiftLint focuses on code quality and best practices
|
||||||
|
|
||||||
|
disabled_rules:
|
||||||
|
- line_length
|
||||||
|
- opening_brace
|
||||||
|
- function_parameter_count
|
||||||
|
- nesting
|
||||||
|
- large_tuple
|
||||||
|
- type_name
|
||||||
|
- force_unwrapping
|
||||||
|
- blanket_disable_command
|
||||||
|
|
||||||
|
opt_in_rules:
|
||||||
|
- array_init
|
||||||
|
- contains_over_first_not_nil
|
||||||
|
- convenience_type
|
||||||
|
- discouraged_assert
|
||||||
|
- discouraged_object_literal
|
||||||
|
- empty_count
|
||||||
|
- empty_string
|
||||||
|
- empty_xctest_method
|
||||||
|
- explicit_init
|
||||||
|
- fatal_error_message
|
||||||
|
- first_where
|
||||||
|
- force_cast
|
||||||
|
- force_try
|
||||||
|
- implicit_return
|
||||||
|
- joined_default_parameter
|
||||||
|
- last_where
|
||||||
|
- legacy_random
|
||||||
|
- lower_acl_than_parent
|
||||||
|
- multiline_function_chains
|
||||||
|
- multiline_parameters
|
||||||
|
- multiline_parameters_brackets
|
||||||
|
- no_fallthrough_only
|
||||||
|
- operator_usage_whitespace
|
||||||
|
- overridden_super_call
|
||||||
|
- prohibited_super_call
|
||||||
|
- redundant_nil_coalescing
|
||||||
|
- single_test_class
|
||||||
|
- sorted_first_last
|
||||||
|
- static_operator
|
||||||
|
- switch_case_alignment
|
||||||
|
- trailing_closure
|
||||||
|
- unavailable_function
|
||||||
|
- unneeded_parentheses_in_closure_argument
|
||||||
|
- unused_control_flow_label
|
||||||
|
- vertical_whitespace_closing_braces
|
||||||
|
- xct_specific_matcher
|
||||||
|
- xctfail_message
|
||||||
|
- yoda_condition
|
||||||
|
|
||||||
|
multiline_parameters:
|
||||||
|
allows_single_line: false
|
||||||
|
|
||||||
|
excluded:
|
||||||
|
- .build
|
||||||
|
- "**/.build"
|
||||||
|
- DerivedData
|
||||||
|
- Pods
|
||||||
|
- Carthage
|
||||||
|
- .git
|
||||||
|
- node_modules
|
||||||
|
|
@ -207,6 +207,7 @@ struct TritonEnvironment: TritonEnvironmentProtocol {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
authSessionServiceFactory: any AuthSessionServiceFactoryProtocol,
|
authSessionServiceFactory: any AuthSessionServiceFactoryProtocol,
|
||||||
sessionServiceFactory: any SessionServiceFactoryProtocol,
|
sessionServiceFactory: any SessionServiceFactoryProtocol,
|
||||||
|
|
@ -233,11 +234,9 @@ struct TritonEnvironment: TritonEnvironmentProtocol {
|
||||||
allocation: .static
|
allocation: .static
|
||||||
) { container in
|
) { container in
|
||||||
let authSessionService = container.resolve() as any AuthSessionServiceProtocol
|
let authSessionService = container.resolve() as any AuthSessionServiceProtocol
|
||||||
return networkClient.makeOMGAPIClient(
|
return networkClient.makeOMGAPIClient {
|
||||||
authTokenProvider: {
|
|
||||||
await authSessionService.accessToken
|
await authSessionService.accessToken
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
container.register(
|
container.register(
|
||||||
|
|
@ -375,4 +374,5 @@ struct TritonEnvironment: TritonEnvironmentProtocol {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ struct TritonScene: Scene {
|
||||||
#endif
|
#endif
|
||||||
.environment(makeAccountUpdateService())
|
.environment(makeAccountUpdateService())
|
||||||
.handlesExternalEvents(
|
.handlesExternalEvents(
|
||||||
preferring: Set(arrayLiteral: "viewer"),
|
preferring: ["viewer"],
|
||||||
allowing: Set(arrayLiteral: "*")
|
allowing: ["*"]
|
||||||
)
|
)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
environment
|
environment
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,11 @@ actor AccountUpdateRepository: AccountUpdateRepositoryProtocol {
|
||||||
await fetchAccountInformation()
|
await fetchAccountInformation()
|
||||||
}
|
}
|
||||||
|
|
||||||
for await isLoggedIn in authSessionService.observeLoginState() {
|
for await isLoggedIn in authSessionService.observeLoginState() where isLoggedIn {
|
||||||
if isLoggedIn {
|
|
||||||
await fetchAccountInformation()
|
await fetchAccountInformation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private func fetchAccountInformation() async {
|
private func fetchAccountInformation() async {
|
||||||
guard await authSessionService.isLoggedIn else { return }
|
guard await authSessionService.isLoggedIn else { return }
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,11 @@ final class AuthAppViewModel {
|
||||||
let currentState = await authSessionService.isLoggedIn
|
let currentState = await authSessionService.isLoggedIn
|
||||||
isLoggedIn = currentState
|
isLoggedIn = currentState
|
||||||
|
|
||||||
for await loginState in authSessionService.observeLoginState() {
|
for await loginState in authSessionService.observeLoginState() where isLoggedIn != loginState {
|
||||||
if isLoggedIn != loginState {
|
|
||||||
isLoggedIn = loginState
|
isLoggedIn = loginState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
observationTask?.cancel()
|
observationTask?.cancel()
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ final class AuthSessionServiceTests: XCTestCase {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testObserveLoginStateYieldsCurrentState() async {
|
func testObserveLoginStateYieldsCurrentState() async throws {
|
||||||
// Given
|
// Given
|
||||||
let initialState = await service.isLoggedIn
|
let initialState = await service.isLoggedIn
|
||||||
|
|
||||||
|
|
@ -97,9 +97,8 @@ final class AuthSessionServiceTests: XCTestCase {
|
||||||
var iterator = stream.makeAsyncIterator()
|
var iterator = stream.makeAsyncIterator()
|
||||||
let firstValue = await iterator.next()
|
let firstValue = await iterator.next()
|
||||||
|
|
||||||
XCTAssertEqual(
|
XCTAssertFalse(
|
||||||
firstValue,
|
try XCTUnwrap(firstValue),
|
||||||
false,
|
|
||||||
"It should yielded the first value correctly"
|
"It should yielded the first value correctly"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -185,10 +185,10 @@ public struct SelectionToolbarItem<Option: Hashable & CaseIterable>: View {
|
||||||
DropdownMenuView(
|
DropdownMenuView(
|
||||||
options: options,
|
options: options,
|
||||||
selection: selection,
|
selection: selection,
|
||||||
itemLabel: itemLabel,
|
itemLabel: itemLabel
|
||||||
label: {
|
) {
|
||||||
AnyView(style.makeLabel(helpText: helpText ?? style.defaultHelpText))
|
let helpText = helpText ?? style.defaultHelpText
|
||||||
}
|
return AnyView(style.makeLabel(helpText: helpText))
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,16 @@ public struct TagListView: View {
|
||||||
#Preview("Regular Tags") {
|
#Preview("Regular Tags") {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: ["swift", "ios", "macos"],
|
tags: ["swift", "ios", "macos"],
|
||||||
helpText: { "Select \($0)" }
|
helpText: { "Select \($0)" },
|
||||||
) { _ in }
|
action: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview("Remove Tags") {
|
#Preview("Remove Tags") {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: ["swift", "ios", "macos"],
|
tags: ["swift", "ios", "macos"],
|
||||||
style: .remove,
|
style: .remove,
|
||||||
helpText: { "Remove \($0)" }
|
helpText: { "Remove \($0)" },
|
||||||
) { _ in }
|
action: { _ in }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import Testing
|
import Testing
|
||||||
@testable import FoundationExtensions
|
@testable import FoundationExtensions
|
||||||
|
|
||||||
|
// swiftlint:disable file_length type_body_length
|
||||||
|
|
||||||
@Suite("ArrayContains Tests")
|
@Suite("ArrayContains Tests")
|
||||||
struct ArrayContainsTests {
|
struct ArrayContainsTests {
|
||||||
|
|
||||||
|
|
@ -535,3 +537,5 @@ struct ArrayContainsTests {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:enable file_length type_body_length
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ struct StringSlugTests {
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
#expect(
|
#expect(
|
||||||
result == "",
|
result.isEmpty,
|
||||||
"It should handle empty string"
|
"It should handle empty string"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ struct StringSlugTests {
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
#expect(
|
#expect(
|
||||||
result == "",
|
result.isEmpty,
|
||||||
"It should handle string with only whitespace"
|
"It should handle string with only whitespace"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
@testable import FoundationExtensions
|
@testable import FoundationExtensions
|
||||||
|
|
||||||
|
// swiftlint:disable file_length type_body_length
|
||||||
|
|
||||||
@Suite("StringWeblog Tests")
|
@Suite("StringWeblog Tests")
|
||||||
struct StringWeblogTests {
|
struct StringWeblogTests {
|
||||||
|
|
||||||
|
|
@ -496,3 +498,5 @@ struct StringWeblogTests {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:enable file_length type_body_length
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ struct NowEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
networkServiceFactory: NowNetworkServiceFactoryProtocol,
|
networkServiceFactory: NowNetworkServiceFactoryProtocol,
|
||||||
persistenceServiceFactory: NowPersistenceServiceFactoryProtocol,
|
persistenceServiceFactory: NowPersistenceServiceFactoryProtocol,
|
||||||
|
|
@ -113,4 +114,5 @@ struct NowEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@
|
||||||
count: Int,
|
count: Int,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
let now = Now(
|
let now = Now(
|
||||||
listed: true,
|
listed: true,
|
||||||
markdown: "Foobar \(i)",
|
markdown: "Foobar \(index)",
|
||||||
submitted: true,
|
submitted: true,
|
||||||
timestamp: 123_123 * Double(i),
|
timestamp: 123_123 * Double(index),
|
||||||
address: "otaviocc"
|
address: "otaviocc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchNowPage(for address: String) async throws {}
|
func fetchNowPage(
|
||||||
func updateNowPage(address: String, content: String, listed: Bool) async throws {}
|
for address: String
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
|
func updateNowPage(
|
||||||
|
address: String,
|
||||||
|
content: String,
|
||||||
|
listed: Bool
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,12 @@
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchNowPage() async throws {}
|
func fetchNowPage() async throws {}
|
||||||
func updateNowPage(address: String, content: String, isListed: Bool) async throws {}
|
|
||||||
|
func updateNowPage(
|
||||||
|
address: String,
|
||||||
|
content: String,
|
||||||
|
isListed: Bool
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@ import XCTest
|
||||||
|
|
||||||
final class NowTests: XCTestCase {
|
final class NowTests: XCTestCase {
|
||||||
|
|
||||||
|
// swiftlint:disable:next empty_xctest_method
|
||||||
func testExample() throws {}
|
func testExample() throws {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,4 @@ public struct CreateOrUpdatePasteRequest: Encodable, Sendable {
|
||||||
let title: String
|
let title: String
|
||||||
let content: String
|
let content: String
|
||||||
let listed: Bool
|
let listed: Bool
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
|
||||||
|
|
||||||
init(
|
|
||||||
title: String,
|
|
||||||
content: String,
|
|
||||||
listed: Bool
|
|
||||||
) {
|
|
||||||
self.title = title
|
|
||||||
self.content = content
|
|
||||||
self.listed = listed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,4 @@ public struct CreatePURLRequest: Encodable, Sendable {
|
||||||
let address: String
|
let address: String
|
||||||
let name: String
|
let name: String
|
||||||
let url: String
|
let url: String
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
|
||||||
|
|
||||||
init(
|
|
||||||
address: String,
|
|
||||||
name: String,
|
|
||||||
url: String
|
|
||||||
) {
|
|
||||||
self.address = address
|
|
||||||
self.name = name
|
|
||||||
self.url = url
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,4 @@ public struct UpdateNowPageRequest: Encodable, Sendable {
|
||||||
|
|
||||||
let content: String
|
let content: String
|
||||||
let listed: Int
|
let listed: Int
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
|
||||||
|
|
||||||
init(
|
|
||||||
content: String,
|
|
||||||
listed: Int
|
|
||||||
) {
|
|
||||||
self.content = content
|
|
||||||
self.listed = listed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,4 @@ public struct UpdateWebpageRequest: Encodable, Sendable {
|
||||||
|
|
||||||
let content: String
|
let content: String
|
||||||
let publish: Bool
|
let publish: Bool
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
|
||||||
|
|
||||||
init(
|
|
||||||
content: String,
|
|
||||||
publish: Bool
|
|
||||||
) {
|
|
||||||
self.content = content
|
|
||||||
self.publish = publish
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,4 @@ public struct UploadPictureRequest: Encodable, Sendable {
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
|
|
||||||
let pic: String
|
let pic: String
|
||||||
|
|
||||||
// MARK: - Lifecycle
|
|
||||||
|
|
||||||
init(
|
|
||||||
pic: String
|
|
||||||
) {
|
|
||||||
self.pic = pic
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,22 +40,22 @@ struct AuthRequestFactoryTests {
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "client_id" }),
|
queryItems.contains { $0.name == "client_id" },
|
||||||
"It should include client_id parameter"
|
"It should include client_id parameter"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "scope" && $0.value == "everything" }),
|
queryItems.contains { $0.name == "scope" && $0.value == "everything" },
|
||||||
"It should include scope parameter with 'everything' value"
|
"It should include scope parameter with 'everything' value"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "response_type" && $0.value == "code" }),
|
queryItems.contains { $0.name == "response_type" && $0.value == "code" },
|
||||||
"It should include response_type parameter with 'code' value"
|
"It should include response_type parameter with 'code' value"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "redirect_uri" }),
|
queryItems.contains { $0.name == "redirect_uri" },
|
||||||
"It should include redirect_uri parameter"
|
"It should include redirect_uri parameter"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -82,27 +82,27 @@ struct AuthRequestFactoryTests {
|
||||||
let queryItems = request.queryItems
|
let queryItems = request.queryItems
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "client_id" }),
|
queryItems.contains { $0.name == "client_id" },
|
||||||
"It should include client_id query parameter"
|
"It should include client_id query parameter"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "client_secret" }),
|
queryItems.contains { $0.name == "client_secret" },
|
||||||
"It should include client_secret query parameter"
|
"It should include client_secret query parameter"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "redirect_uri" }),
|
queryItems.contains { $0.name == "redirect_uri" },
|
||||||
"It should include redirect_uri query parameter"
|
"It should include redirect_uri query parameter"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "code" && $0.value == authCode }),
|
queryItems.contains { $0.name == "code" && $0.value == authCode },
|
||||||
"It should include code query parameter with provided auth code"
|
"It should include code query parameter with provided auth code"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
queryItems.contains(where: { $0.name == "scope" && $0.value == "everything" }),
|
queryItems.contains { $0.name == "scope" && $0.value == "everything" },
|
||||||
"It should include scope query parameter"
|
"It should include scope query parameter"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ struct PicsRequestFactoryTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test("It should create picture edit request with empty tags array")
|
@Test("It should create picture edit request with empty tags array")
|
||||||
func makeEditPictureRequest_withOnlyWithEmptyTagsArray_createsRequest() {
|
func makeEditPictureRequest_withOnlyWithEmptyTagsArray_createsRequest() throws {
|
||||||
// Given
|
// Given
|
||||||
let address = "dave"
|
let address = "dave"
|
||||||
let pictureID = "pic-456"
|
let pictureID = "pic-456"
|
||||||
|
|
@ -256,23 +256,26 @@ struct PicsRequestFactoryTests {
|
||||||
"It should use PUT method"
|
"It should use PUT method"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let body = try #require(request.body)
|
||||||
|
let bodyTags = try #require(body.tags)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
request.body?.tags == "",
|
bodyTags.isEmpty == true,
|
||||||
"It should include tags in request body"
|
"It should include tags in request body"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
request.body?.caption == nil,
|
body.caption == nil,
|
||||||
"It should have nil caption when not provided"
|
"It should have nil caption when not provided"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
request.body?.alt == nil,
|
body.alt == nil,
|
||||||
"It should have nil alt text when not provided"
|
"It should have nil alt text when not provided"
|
||||||
)
|
)
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
request.body?.isHidden == nil,
|
body.isHidden == nil,
|
||||||
"It should have nil isHidden when not provided"
|
"It should have nil isHidden when not provided"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ struct PURLsEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
networkServiceFactory: PURLsNetworkServiceFactoryProtocol,
|
networkServiceFactory: PURLsNetworkServiceFactoryProtocol,
|
||||||
persistenceServiceFactory: PURLsPersistenceServiceFactoryProtocol,
|
persistenceServiceFactory: PURLsPersistenceServiceFactoryProtocol,
|
||||||
|
|
@ -123,4 +124,5 @@ struct PURLsEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,14 @@
|
||||||
|
|
||||||
private final class FakeClipboardService: ClipboardServiceProtocol {
|
private final class FakeClipboardService: ClipboardServiceProtocol {
|
||||||
|
|
||||||
func copy(_ string: String) {}
|
func copy(
|
||||||
func copy(_ data: Data, type: String) {}
|
_ string: String
|
||||||
|
) {}
|
||||||
|
|
||||||
|
func copy(
|
||||||
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@
|
||||||
count: Int,
|
count: Int,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
let purl = PURL(
|
let purl = PURL(
|
||||||
name: "purl\(i)",
|
name: "purl\(index)",
|
||||||
url: URL(string: "http://subdomain\(i).otavio.lol")!,
|
url: URL(string: "http://subdomain\(index).otavio.lol")!,
|
||||||
address: "otaviocc"
|
address: "otaviocc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPURLs(for address: String) {}
|
func fetchPURLs(
|
||||||
func addPURL(address: String, name: String, url: String) {}
|
for address: String
|
||||||
func deletePURL(address: String, name: String) async throws {}
|
) {}
|
||||||
|
|
||||||
|
func addPURL(
|
||||||
|
address: String,
|
||||||
|
name: String,
|
||||||
|
url: String
|
||||||
|
) {}
|
||||||
|
|
||||||
|
func deletePURL(
|
||||||
|
address: String,
|
||||||
|
name: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,17 @@
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchPURLs() {}
|
func fetchPURLs() {}
|
||||||
func addPURL(address: String, name: String, url: String) {}
|
|
||||||
func deletePURL(address: String, name: String) async throws {}
|
func addPURL(
|
||||||
|
address: String,
|
||||||
|
name: String,
|
||||||
|
url: String
|
||||||
|
) {}
|
||||||
|
|
||||||
|
func deletePURL(
|
||||||
|
address: String,
|
||||||
|
name: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@ import XCTest
|
||||||
|
|
||||||
final class PURLsTests: XCTestCase {
|
final class PURLsTests: XCTestCase {
|
||||||
|
|
||||||
|
// swiftlint:disable:next empty_xctest_method
|
||||||
func testExample() throws {}
|
func testExample() throws {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ struct PastebinEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
networkServiceFactory: PastebinNetworkServiceFactoryProtocol,
|
networkServiceFactory: PastebinNetworkServiceFactoryProtocol,
|
||||||
persistenceServiceFactory: PastebinPersistenceServiceFactoryProtocol,
|
persistenceServiceFactory: PastebinPersistenceServiceFactoryProtocol,
|
||||||
|
|
@ -123,4 +124,5 @@ struct PastebinEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,11 @@
|
||||||
private final class FakeClipboardService: ClipboardServiceProtocol {
|
private final class FakeClipboardService: ClipboardServiceProtocol {
|
||||||
|
|
||||||
func copy(_ string: String) {}
|
func copy(_ string: String) {}
|
||||||
func copy(_ data: Data, type: String) {}
|
|
||||||
|
func copy(
|
||||||
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@
|
||||||
count: Int,
|
count: Int,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
let paste = Paste(
|
let paste = Paste(
|
||||||
title: "paste\(i).md",
|
title: "paste\(index).md",
|
||||||
content: "hello, world!",
|
content: "hello, world!",
|
||||||
timestamp: 123_123_123,
|
timestamp: 123_123_123,
|
||||||
address: "otaviocc",
|
address: "otaviocc",
|
||||||
listed: i % 2 == 0
|
listed: index % 2 == 0
|
||||||
)
|
)
|
||||||
|
|
||||||
container.mainContext.insert(
|
container.mainContext.insert(
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPastes(for address: String) async throws {}
|
func fetchPastes(
|
||||||
func createOrUpdatePaste(address: String, title: String, content: String, listed: Bool) async throws {}
|
for address: String
|
||||||
func deletePaste(address: String, title: String) async throws {}
|
) async throws {}
|
||||||
|
|
||||||
|
func createOrUpdatePaste(
|
||||||
|
address: String,
|
||||||
|
title: String,
|
||||||
|
content: String,
|
||||||
|
listed: Bool
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
|
func deletePaste(
|
||||||
|
address: String,
|
||||||
|
title: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,18 @@
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchPastes() async throws {}
|
func fetchPastes() async throws {}
|
||||||
func createOrUpdatePaste(address: String, title: String, content: String, isListed: Bool) async throws {}
|
|
||||||
func deletePaste(address: String, title: String) async throws {}
|
func createOrUpdatePaste(
|
||||||
|
address: String,
|
||||||
|
title: String,
|
||||||
|
content: String,
|
||||||
|
isListed: Bool
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
|
func deletePaste(
|
||||||
|
address: String,
|
||||||
|
title: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@ import XCTest
|
||||||
|
|
||||||
final class PastebinTests: XCTestCase {
|
final class PastebinTests: XCTestCase {
|
||||||
|
|
||||||
|
// swiftlint:disable:next empty_xctest_method
|
||||||
func testExample() throws {}
|
func testExample() throws {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ struct PicsEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
networkServiceFactory: PicsNetworkServiceFactoryProtocol,
|
networkServiceFactory: PicsNetworkServiceFactoryProtocol,
|
||||||
persistenceServiceFactory: PicsPersistenceServiceFactoryProtocol,
|
persistenceServiceFactory: PicsPersistenceServiceFactoryProtocol,
|
||||||
|
|
@ -119,4 +120,5 @@ struct PicsEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,14 @@
|
||||||
|
|
||||||
private final class FakeClipboardService: ClipboardServiceProtocol {
|
private final class FakeClipboardService: ClipboardServiceProtocol {
|
||||||
|
|
||||||
func copy(_ string: String) {}
|
func copy(
|
||||||
func copy(_ data: Data, type: String) {}
|
_ string: String
|
||||||
|
) {}
|
||||||
|
|
||||||
|
func copy(
|
||||||
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,15 @@
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchPictures(for address: String) async throws -> [PictureResponse] { [] }
|
func fetchPictures(
|
||||||
func deletePicture(address: String, pictureID: String) async throws {}
|
for address: String
|
||||||
|
) async throws -> [PictureResponse] { [] }
|
||||||
|
|
||||||
|
func deletePicture(
|
||||||
|
address: String,
|
||||||
|
pictureID: String
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
func updatePicture(
|
func updatePicture(
|
||||||
address: String,
|
address: String,
|
||||||
pictureID: String,
|
pictureID: String,
|
||||||
|
|
@ -21,6 +28,7 @@
|
||||||
alt: String,
|
alt: String,
|
||||||
tags: [String]
|
tags: [String]
|
||||||
) async throws {}
|
) async throws {}
|
||||||
|
|
||||||
func uploadPicture(
|
func uploadPicture(
|
||||||
address: String,
|
address: String,
|
||||||
data: Data,
|
data: Data,
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,12 @@
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchPictures() async throws {}
|
func fetchPictures() async throws {}
|
||||||
func deletePicture(address: String, pictureID: String) async throws {}
|
|
||||||
|
func deletePicture(
|
||||||
|
address: String,
|
||||||
|
pictureID: String
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
func updatePicture(
|
func updatePicture(
|
||||||
address: String,
|
address: String,
|
||||||
pictureID: String,
|
pictureID: String,
|
||||||
|
|
@ -47,6 +52,7 @@
|
||||||
alt: String,
|
alt: String,
|
||||||
tags: [String]
|
tags: [String]
|
||||||
) async throws {}
|
) async throws {}
|
||||||
|
|
||||||
func uploadPicture(
|
func uploadPicture(
|
||||||
address: String,
|
address: String,
|
||||||
data: Data,
|
data: Data,
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@
|
||||||
count: Int = 3,
|
count: Int = 3,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
SomePicture.makePicture(
|
SomePicture.makePicture(
|
||||||
created: Double(i * i),
|
created: Double(index * index),
|
||||||
in: container
|
in: container
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,12 +98,13 @@ struct EditPictureView: View {
|
||||||
if !viewModel.suggestedTags.isEmpty {
|
if !viewModel.suggestedTags.isEmpty {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: viewModel.suggestedTags,
|
tags: viewModel.suggestedTags,
|
||||||
helpText: { "Add existing tag '\($0)'" }
|
helpText: { "Add existing tag '\($0)'" },
|
||||||
) { tag in
|
action: { tag in
|
||||||
withAnimation {
|
withAnimation {
|
||||||
viewModel.addTag(tag)
|
viewModel.addTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,12 +114,13 @@ struct EditPictureView: View {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: viewModel.tags,
|
tags: viewModel.tags,
|
||||||
style: .remove,
|
style: .remove,
|
||||||
helpText: { "Remove tag '\($0)'" }
|
helpText: { "Remove tag '\($0)'" },
|
||||||
) { tag in
|
action: { tag in
|
||||||
withAnimation {
|
withAnimation {
|
||||||
viewModel.removeTag(tag)
|
viewModel.removeTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ struct PicturesListView: View {
|
||||||
_pictures = .init(viewModel.fetchDescriptor())
|
_pictures = .init(viewModel.fetchDescriptor())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK; - Public
|
// MARK: - Public
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
|
|
|
||||||
|
|
@ -209,12 +209,13 @@ struct UploadView: View {
|
||||||
if !viewModel.suggestedTags.isEmpty {
|
if !viewModel.suggestedTags.isEmpty {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: viewModel.suggestedTags,
|
tags: viewModel.suggestedTags,
|
||||||
helpText: { "Add existing tag '\($0)'" }
|
helpText: { "Add existing tag '\($0)'" },
|
||||||
) { tag in
|
action: { tag in
|
||||||
withAnimation(.easeInOut(duration: 0.2)) {
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
viewModel.addTag(tag)
|
viewModel.addTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,12 +225,13 @@ struct UploadView: View {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: viewModel.tags,
|
tags: viewModel.tags,
|
||||||
style: .remove,
|
style: .remove,
|
||||||
helpText: { "Remove tag '\($0)'" }
|
helpText: { "Remove tag '\($0)'" },
|
||||||
) { tag in
|
action: { tag in
|
||||||
withAnimation(.easeInOut(duration: 0.2)) {
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
viewModel.removeTag(tag)
|
viewModel.removeTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ struct StatusEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
repositoryFactory: StatusRepositoryFactoryProtocol,
|
repositoryFactory: StatusRepositoryFactoryProtocol,
|
||||||
networkServiceFactory: StatusNetworkServiceFactoryProtocol,
|
networkServiceFactory: StatusNetworkServiceFactoryProtocol,
|
||||||
|
|
@ -120,4 +121,5 @@ struct StatusEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,14 @@
|
||||||
|
|
||||||
private final class FakeClipboardService: ClipboardServiceProtocol {
|
private final class FakeClipboardService: ClipboardServiceProtocol {
|
||||||
|
|
||||||
func copy(_ string: String) {}
|
func copy(
|
||||||
func copy(_ data: Data, type: String) {}
|
_ string: String
|
||||||
|
) {}
|
||||||
|
|
||||||
|
func copy(
|
||||||
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@
|
||||||
count: Int,
|
count: Int,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
let status = Status(
|
let status = Status(
|
||||||
username: "user\(i)",
|
username: "user\(index)",
|
||||||
statusID: "(i)",
|
statusID: "(index)",
|
||||||
timestamp: Double(i),
|
timestamp: Double(index),
|
||||||
icon: "🤣",
|
icon: "🤣",
|
||||||
content: "Nulla purus urna, bibendum nec purus."
|
content: "Nulla purus urna, bibendum nec purus."
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,10 @@ public struct StatusApp: View {
|
||||||
ToolbarItemGroup {
|
ToolbarItemGroup {
|
||||||
SelectionToolbarItem(
|
SelectionToolbarItem(
|
||||||
options: StatusListFilter.allCases,
|
options: StatusListFilter.allCases,
|
||||||
selection: $filter,
|
selection: $filter
|
||||||
itemLabel: { $0.localizedTitle }
|
) { label in
|
||||||
)
|
label.localizedTitle
|
||||||
|
}
|
||||||
.selectionToolbarItemStyle(FilterSelectionToolbarItemStyle())
|
.selectionToolbarItemStyle(FilterSelectionToolbarItemStyle())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,13 @@ struct ClipboardService: ClipboardServiceProtocol {
|
||||||
service.copy(string)
|
service.copy(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copy(_ data: Data, type: String) {
|
func copy(
|
||||||
service.copy(data, type: type)
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {
|
||||||
|
service.copy(
|
||||||
|
data,
|
||||||
|
type: type
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,10 @@
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copy(_ data: Data, type: String) {
|
func copy(
|
||||||
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {
|
||||||
NSPasteboard
|
NSPasteboard
|
||||||
.general
|
.general
|
||||||
.clearContents()
|
.clearContents()
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ struct WeblogEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
networkServiceFactory: WeblogNetworkServiceFactoryProtocol,
|
networkServiceFactory: WeblogNetworkServiceFactoryProtocol,
|
||||||
persistenceServiceFactory: WeblogPersistenceServiceFactoryProtocol,
|
persistenceServiceFactory: WeblogPersistenceServiceFactoryProtocol,
|
||||||
|
|
@ -119,4 +120,5 @@ struct WeblogEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,14 @@
|
||||||
|
|
||||||
private final class FakeClipboardService: ClipboardServiceProtocol {
|
private final class FakeClipboardService: ClipboardServiceProtocol {
|
||||||
|
|
||||||
func copy(_ string: String) {}
|
func copy(
|
||||||
func copy(_ data: Data, type: String) {}
|
_ string: String
|
||||||
|
) {}
|
||||||
|
|
||||||
|
func copy(
|
||||||
|
_ data: Data,
|
||||||
|
type: String
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
static func makeEntryResponses(count: Int = 5) -> [EntryResponse] {
|
static func makeEntryResponses(count: Int = 5) -> [EntryResponse] {
|
||||||
(0..<count).map { i in
|
(0..<count).map { index in
|
||||||
makeEntryResponse(
|
makeEntryResponse(
|
||||||
id: "entry-\(i)",
|
id: "entry-\(index)",
|
||||||
location: "test-entry-\(i)",
|
location: "test-entry-\(index)",
|
||||||
date: Double(1_700_000_000 + (i * 86400)),
|
date: Double(1_700_000_000 + (index * 86400)),
|
||||||
status: i % 3 == 0 ? "draft" : "published",
|
status: index % 3 == 0 ? "draft" : "published",
|
||||||
title: "Test Entry \(i)",
|
title: "Test Entry \(index)",
|
||||||
body: "Content for test entry \(i)"
|
body: "Content for test entry \(index)"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,14 @@
|
||||||
count: Int,
|
count: Int,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
let entry = WeblogEntry(
|
let entry = WeblogEntry(
|
||||||
id: "entry-\(i)",
|
id: "entry-\(index)",
|
||||||
title: "Test Entry \(i)",
|
title: "Test Entry \(index)",
|
||||||
body: "This is the body for test entry \(i). Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
body: "This is the body for test entry \(index). Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||||
date: Double(1_700_000_000 + (i * 86400)),
|
date: Double(1_700_000_000 + (index * 86400)),
|
||||||
status: i % 3 == 0 ? "draft" : "published",
|
status: index % 3 == 0 ? "draft" : "published",
|
||||||
location: "test-entry-\(i)",
|
location: "test-entry-\(index)",
|
||||||
address: "otaviocc"
|
address: "otaviocc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,16 @@
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchWeblogEntry(for address: String, entryID: String) async throws -> EntryResponse {
|
func fetchWeblogEntry(
|
||||||
|
for address: String,
|
||||||
|
entryID: String
|
||||||
|
) async throws -> EntryResponse {
|
||||||
EntryResponseMother.makeEntryResponse()
|
EntryResponseMother.makeEntryResponse()
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchWeblogEntries(for address: String) async throws -> [EntryResponse] {
|
func fetchWeblogEntries(
|
||||||
|
for address: String
|
||||||
|
) async throws -> [EntryResponse] {
|
||||||
EntryResponseMother.makeEntryResponses(count: 2)
|
EntryResponseMother.makeEntryResponses(count: 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +46,10 @@
|
||||||
EntryResponseMother.makeEntryResponse()
|
EntryResponseMother.makeEntryResponse()
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteWeblogEntry(address: String, entryID: String) async throws {}
|
func deleteWeblogEntry(
|
||||||
|
address: String,
|
||||||
|
entryID: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,11 @@
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchEntries() async throws {}
|
func fetchEntries() async throws {}
|
||||||
func deleteEntry(address: String, entryID: String) async throws {}
|
|
||||||
|
func deleteEntry(
|
||||||
|
address: String,
|
||||||
|
entryID: String
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
func createOrUpdateEntry(
|
func createOrUpdateEntry(
|
||||||
address: String,
|
address: String,
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ struct EditorView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
// swiftlint:disable:next function_body_length
|
||||||
private func makeSidebarView() -> some View {
|
private func makeSidebarView() -> some View {
|
||||||
Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 16) {
|
Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 16) {
|
||||||
GridRow(alignment: .firstTextBaseline) {
|
GridRow(alignment: .firstTextBaseline) {
|
||||||
|
|
@ -146,12 +147,13 @@ struct EditorView: View {
|
||||||
if !viewModel.suggestedTags.isEmpty {
|
if !viewModel.suggestedTags.isEmpty {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: viewModel.suggestedTags,
|
tags: viewModel.suggestedTags,
|
||||||
helpText: { "Add existing tag '\($0)'" }
|
helpText: { "Add existing tag '\($0)'" },
|
||||||
) { tag in
|
action: { tag in
|
||||||
withAnimation {
|
withAnimation {
|
||||||
viewModel.addTag(tag)
|
viewModel.addTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,12 +172,13 @@ struct EditorView: View {
|
||||||
TagListView(
|
TagListView(
|
||||||
tags: viewModel.tags,
|
tags: viewModel.tags,
|
||||||
style: .remove,
|
style: .remove,
|
||||||
helpText: { "Remove tag '\($0)'" }
|
helpText: { "Remove tag '\($0)'" },
|
||||||
) { tag in
|
action: { tag in
|
||||||
withAnimation {
|
withAnimation {
|
||||||
viewModel.removeTag(tag)
|
viewModel.removeTag(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ struct WeblogEntriesListView: View {
|
||||||
_entries = .init(viewModel.fetchDescriptor())
|
_entries = .init(viewModel.fetchDescriptor())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK; - Public
|
// MARK: - Public
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ struct WebpageEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable function_body_length
|
||||||
init(
|
init(
|
||||||
networkServiceFactory: WebpageNetworkServiceFactoryProtocol,
|
networkServiceFactory: WebpageNetworkServiceFactoryProtocol,
|
||||||
persistenceServiceFactory: WebpagePersistenceServiceFactoryProtocol,
|
persistenceServiceFactory: WebpagePersistenceServiceFactoryProtocol,
|
||||||
|
|
@ -112,4 +113,5 @@ struct WebpageEnvironment {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// swiftlint:enable function_body_length
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@
|
||||||
count: Int,
|
count: Int,
|
||||||
in container: ModelContainer
|
in container: ModelContainer
|
||||||
) {
|
) {
|
||||||
for i in 0..<count {
|
for index in 0..<count {
|
||||||
let page = Webpage(
|
let page = Webpage(
|
||||||
address: "otaviocc",
|
address: "otaviocc",
|
||||||
markdown: "Foobar \(i)",
|
markdown: "Foobar \(index)",
|
||||||
timestamp: 123_123 * Double(i)
|
timestamp: 123_123 * Double(index)
|
||||||
)
|
)
|
||||||
|
|
||||||
container.mainContext.insert(
|
container.mainContext.insert(
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchWebpage(for address: String) async throws {}
|
func fetchWebpage(
|
||||||
func updateWebpage(address: String, content: String) async throws {}
|
for address: String
|
||||||
|
) async throws {}
|
||||||
|
|
||||||
|
func updateWebpage(
|
||||||
|
address: String,
|
||||||
|
content: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,11 @@
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func fetchWebpage() async throws {}
|
func fetchWebpage() async throws {}
|
||||||
func updateWebpage(address: String, content: String) async throws {}
|
|
||||||
|
func updateWebpage(
|
||||||
|
address: String,
|
||||||
|
content: String
|
||||||
|
) async throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,6 @@ import XCTest
|
||||||
|
|
||||||
final class WebpageTests: XCTestCase {
|
final class WebpageTests: XCTestCase {
|
||||||
|
|
||||||
|
// swiftlint:disable:next empty_xctest_method
|
||||||
func testExample() throws {}
|
func testExample() throws {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue