import Foundation import Testing @testable import OrgSocialKit private let sampleProfile = """ #+TITLE: My Feed #+NICK: andros #+DESCRIPTION: Developer. #+FOLLOW: shom https://shom.dev/social.org #+FOLLOW: https://tanrax.com/social.org * Posts ** 2025-01-01T10:00:00+01:00 :PROPERTIES: :CLIENT: org-social-ios :END: Hello! """ @Suite("ProfileWriter – keyword editing") struct ProfileWriterKeywordTests { let pw = ProfileWriter() @Test("setKeyword replaces existing value") func replaceExisting() { let result = pw.setKeyword("NICK", value: "newNick", in: sampleProfile) #expect(result.contains("#+NICK: newNick")) #expect(!result.contains("#+NICK: andros")) } @Test("setKeyword inserts new keyword before * Posts") func insertBeforePosts() { let result = pw.setKeyword("AVATAR", value: "https://example.com/avatar.jpg", in: sampleProfile) #expect(result.contains("#+AVATAR: https://example.com/avatar.jpg")) let avatarIdx = result.range(of: "#+AVATAR:")!.lowerBound let postsIdx = result.range(of: "* Posts")!.lowerBound #expect(avatarIdx < postsIdx) } @Test("setKeyword is case-insensitive on keyword") func caseInsensitive() { let result = pw.setKeyword("description", value: "New bio", in: sampleProfile) #expect(result.contains("#+DESCRIPTION: New bio")) #expect(!result.contains("#+DESCRIPTION: Developer.")) } @Test("removeKeyword deletes the line") func removeKeyword() { let result = pw.removeKeyword("DESCRIPTION", from: sampleProfile) #expect(!result.contains("#+DESCRIPTION:")) #expect(result.contains("#+NICK: andros")) } @Test("removeKeyword is a no-op when keyword absent") func removeAbsent() { let result = pw.removeKeyword("AVATAR", from: sampleProfile) #expect(result == sampleProfile) } @Test("setMultiKeyword replaces all LINK lines") func setMultiLink() { let withLinks = sampleProfile + "\n#+LINK: https://old.example.com" let result = pw.setMultiKeyword("LINK", values: ["https://a.com", "https://b.com"], in: withLinks) #expect(result.contains("#+LINK: https://a.com")) #expect(result.contains("#+LINK: https://b.com")) #expect(!result.contains("https://old.example.com")) } @Test("setMultiKeyword with empty values removes all lines") func removeAllLinks() { let withLinks = sampleProfile + "\n#+LINK: https://old.example.com" let result = pw.setMultiKeyword("LINK", values: [], in: withLinks) #expect(!result.contains("#+LINK:")) } } @Suite("ProfileWriter – follow management") struct ProfileWriterFollowTests { let pw = ProfileWriter() let newURL = URL(string: "https://friend.example.com/social.org")! @Test("addFollow with nick inserts formatted line") func addFollowWithNick() { let result = pw.addFollow(url: newURL, nick: "friend", to: sampleProfile) #expect(result.contains("#+FOLLOW: friend https://friend.example.com/social.org")) } @Test("addFollow without nick inserts URL-only line") func addFollowWithoutNick() { let result = pw.addFollow(url: newURL, to: sampleProfile) #expect(result.contains("#+FOLLOW: https://friend.example.com/social.org")) } @Test("addFollow inserts after last existing FOLLOW") func addFollowAfterExisting() { let result = pw.addFollow(url: newURL, nick: "friend", to: sampleProfile) let lines = result.components(separatedBy: "\n") let followLines = lines.enumerated().filter { $0.element.uppercased().hasPrefix("#+FOLLOW:") } let newIdx = followLines.last { $0.element.contains("friend") }?.offset ?? -1 let oldIdx = followLines.first { $0.element.contains("tanrax") }?.offset ?? -1 #expect(newIdx > oldIdx) } @Test("addFollow is idempotent when already following") func addFollowIdempotent() { let existingURL = URL(string: "https://shom.dev/social.org")! let result = pw.addFollow(url: existingURL, nick: "shom", to: sampleProfile) let count = result.components(separatedBy: "\n") .filter { $0.contains("shom.dev") }.count #expect(count == 1) } @Test("removeFollow removes matching line") func removeFollow() { let url = URL(string: "https://shom.dev/social.org")! let result = pw.removeFollow(url: url, from: sampleProfile) #expect(!result.contains("shom.dev")) #expect(result.contains("tanrax.com")) } @Test("removeFollow leaves other follows intact") func removeFollowLeavesOthers() { let url = URL(string: "https://shom.dev/social.org")! let result = pw.removeFollow(url: url, from: sampleProfile) #expect(result.contains("#+FOLLOW: https://tanrax.com/social.org")) } @Test("isFollowing returns true for followed URL") func isFollowingTrue() { let url = URL(string: "https://shom.dev/social.org")! #expect(pw.isFollowing(url: url, in: sampleProfile)) } @Test("isFollowing returns false for unknown URL") func isFollowingFalse() { #expect(!pw.isFollowing(url: newURL, in: sampleProfile)) } }