summaryrefslogtreecommitdiff
path: root/SoraTests/ViewDerivedDataTests.swift
diff options
context:
space:
mode:
Diffstat (limited to 'SoraTests/ViewDerivedDataTests.swift')
-rw-r--r--SoraTests/ViewDerivedDataTests.swift88
1 files changed, 76 insertions, 12 deletions
diff --git a/SoraTests/ViewDerivedDataTests.swift b/SoraTests/ViewDerivedDataTests.swift
index 9152591..c20e9d1 100644
--- a/SoraTests/ViewDerivedDataTests.swift
+++ b/SoraTests/ViewDerivedDataTests.swift
@@ -193,6 +193,58 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
)
}
+ func testPostDetailsImageViewAvoidsForceUnwrappedRuntimeURLs() throws {
+ let source = try loadSource(at: "Sora/Views/Post/Details/PostDetailsImageView.swift")
+ let normalizedSource = strippingCommentsAndStrings(from: source)
+ let forcedShareFallbackURLCount = tokenCount(
+ matching: #"\burl\s*\?\?\s*URL\s*\(\s*string:\s*\)\s*!"#,
+ in: normalizedSource
+ )
+ let forcedSourceURLCount = tokenCount(
+ matching: #"\bURL\s*\(\s*string:\s*source\s*\)\s*!"#,
+ in: normalizedSource
+ )
+ let forcedPostURLBuilderCount = tokenCount(
+ matching: #"\breturn\s+URL\s*\(\s*string:\s*[^)]+\)\s*!"#,
+ in: normalizedSource
+ )
+
+ // swiftlint:disable:next prefer_nimble
+ XCTAssertEqual(
+ forcedShareFallbackURLCount,
+ 0,
+ "Post details share actions should not force unwrap fallback URLs."
+ )
+ // swiftlint:disable:next prefer_nimble
+ XCTAssertEqual(
+ forcedSourceURLCount,
+ 0,
+ "Post details source links should be validated before opening."
+ )
+ // swiftlint:disable:next prefer_nimble
+ XCTAssertEqual(
+ forcedPostURLBuilderCount,
+ 0,
+ "Post details post-url helpers should return optional URLs instead of force-unwrapping."
+ )
+ }
+
+ func testPostDetailsViewAvoidsForceUnwrappedShareURL() throws {
+ let source = try loadSource(at: "Sora/Views/Post/Details/PostDetailsView.swift")
+ let normalizedSource = strippingCommentsAndStrings(from: source)
+ let forcedShareItemCount = tokenCount(
+ matching: #"\bShareLink\s*\(\s*item:\s*imageURL\s*!"#,
+ in: normalizedSource
+ )
+
+ // swiftlint:disable:next prefer_nimble
+ XCTAssertEqual(
+ forcedShareItemCount,
+ 0,
+ "Post details share actions should not force unwrap image URLs."
+ )
+ }
+
func testListViewsAvoidComparatorRandomShuffleSorting() throws {
let listViewSource = try loadSource(at: "Sora/Views/Generic/GenericListView.swift")
let favoritesViewSource = try loadSource(at: "Sora/Views/FavoritesView.swift")
@@ -304,9 +356,11 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
named: "func url(forPosts page: Int, limit: Int, tags: [String]) -> URL?",
from: source
)
- let danbooruCaseStart = try XCTUnwrap(urlBuilderSection.range(of: "case .danbooru:")?.lowerBound)
+ let danbooruCaseStart = try XCTUnwrap(
+ urlBuilderSection.range(of: "case .danbooru:")?.lowerBound)
let danbooruCaseEnd = try XCTUnwrap(
- urlBuilderSection.range(of: "case .moebooru:", range: danbooruCaseStart..<urlBuilderSection.endIndex)?
+ urlBuilderSection.range(
+ of: "case .moebooru:", range: danbooruCaseStart..<urlBuilderSection.endIndex)?
.lowerBound
)
let danbooruSection = String(urlBuilderSection[danbooruCaseStart..<danbooruCaseEnd])
@@ -329,9 +383,11 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
named: "func url(forPosts page: Int, limit: Int, tags: [String]) -> URL?",
from: source
)
- let moebooruCaseStart = try XCTUnwrap(urlBuilderSection.range(of: "case .moebooru:")?.lowerBound)
+ let moebooruCaseStart = try XCTUnwrap(
+ urlBuilderSection.range(of: "case .moebooru:")?.lowerBound)
let moebooruCaseEnd = try XCTUnwrap(
- urlBuilderSection.range(of: "case .gelbooru:", range: moebooruCaseStart..<urlBuilderSection.endIndex)?
+ urlBuilderSection.range(
+ of: "case .gelbooru:", range: moebooruCaseStart..<urlBuilderSection.endIndex)?
.lowerBound
)
let moebooruSection = String(urlBuilderSection[moebooruCaseStart..<moebooruCaseEnd])
@@ -373,7 +429,8 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
in: moebooruTagHelperSection
)
let explicitHoldsBypassCount = tokenCount(
- matching: #"if\s+hasExplicitHoldsFilter\s*\{\s*return\s+tags\.joined\(separator:\s*"\+"\)\s*\}"#,
+ matching:
+ #"if\s+hasExplicitHoldsFilter\s*\{\s*return\s+tags\.joined\(separator:\s*"\+"\)\s*\}"#,
in: moebooruTagHelperSection
)
@@ -394,7 +451,8 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
func testSettingsManagerPersistsShowHeldMoebooruPostsFlag() throws {
let source = try loadSource(at: "Sora/Data/Settings/SettingsManager.swift")
let showHeldSettingCount = tokenCount(
- matching: #"\@AppStorage\("showHeldMoebooruPosts"\)\s*var\s+showHeldMoebooruPosts\s*=\s*false"#,
+ matching:
+ #"\@AppStorage\("showHeldMoebooruPosts"\)\s*var\s+showHeldMoebooruPosts\s*=\s*false"#,
in: source
)
@@ -442,7 +500,8 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
from: source
)
let showHeldBypassCount = tokenCount(
- matching: #"guard\s*!\s*showHeldMoebooruPosts\s*else\s*\{\s*return\s+tags\.joined\(separator:\s*"\+"\)\s*\}"#,
+ matching:
+ #"guard\s*!\s*showHeldMoebooruPosts\s*else\s*\{\s*return\s+tags\.joined\(separator:\s*"\+"\)\s*\}"#,
in: moebooruTagHelperSection
)
@@ -466,9 +525,11 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
named: "func url(forPosts page: Int, limit: Int, tags: [String]) -> URL?",
from: source
)
- let danbooruCaseStart = try XCTUnwrap(urlBuilderSection.range(of: "case .danbooru:")?.lowerBound)
+ let danbooruCaseStart = try XCTUnwrap(
+ urlBuilderSection.range(of: "case .danbooru:")?.lowerBound)
let danbooruCaseEnd = try XCTUnwrap(
- urlBuilderSection.range(of: "case .moebooru:", range: danbooruCaseStart..<urlBuilderSection.endIndex)?
+ urlBuilderSection.range(
+ of: "case .moebooru:", range: danbooruCaseStart..<urlBuilderSection.endIndex)?
.lowerBound
)
let danbooruSection = String(urlBuilderSection[danbooruCaseStart..<danbooruCaseEnd])
@@ -477,7 +538,8 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
from: source
)
let danbooruCursorPageQueryCount = tokenCount(
- matching: #"URLQueryItem\(name:\s*"page",\s*value:\s*danbooruPageToken\(for:\s*page,\s*tags:\s*tags\)\)"#,
+ matching:
+ #"URLQueryItem\(name:\s*"page",\s*value:\s*danbooruPageToken\(for:\s*page,\s*tags:\s*tags\)\)"#,
in: danbooruSection
)
let beforeCursorCount = tokenCount(
@@ -506,7 +568,8 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
from: source
)
let explicitSortGuardCount = tokenCount(
- matching: #"guard\s*!\s*hasExplicitSortTag\(in:\s*tags\)\s*else\s*\{\s*return\s*String\(page\)\s*\}"#,
+ matching:
+ #"guard\s*!\s*hasExplicitSortTag\(in:\s*tags\)\s*else\s*\{\s*return\s*String\(page\)\s*\}"#,
in: pageTokenFunctionSection
)
let sortTagHelperSection = try extractFunction(
@@ -655,7 +718,8 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b
func testDanbooruPostModelUsesOptionalVisibilityDependentFields() throws {
let source = try loadSource(at: "Sora/Data/Danbooru/DanbooruPost.swift")
let optionalFileURLCount = tokenCount(matching: #"let\s+fileURL:\s+String\?"#, in: source)
- let optionalLargeFileURLCount = tokenCount(matching: #"let\s+largeFileURL:\s+String\?"#, in: source)
+ let optionalLargeFileURLCount = tokenCount(
+ matching: #"let\s+largeFileURL:\s+String\?"#, in: source)
let optionalPreviewURLCount = tokenCount(
matching: #"let\s+previewFileURL:\s+String\?"#,
in: source