diff options
Diffstat (limited to 'SoraTests/ViewDerivedDataTests.swift')
| -rw-r--r-- | SoraTests/ViewDerivedDataTests.swift | 88 |
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 |