Files
andros 073d3346ef Fix mention autocomplete: close on Enter, add Orgro; extract inferredNick + tests; bump 1.3 (16)
- MentionAutocompleteField: use \z instead of $ so dropdown closes after Enter
- MentionDirectory: handle path-less feed URLs (e.g. social.orgro.org → orgro)
  via penultimate host segment heuristic
- Extract derivedNick logic to public inferredNick(from:) in OrgSocialKit/Util
- Add URLNickTests covering 16 real relay URL patterns (vhost, root, path-less,
  deep GitHub/Codeberg, tilde, custom filename)
- Bump build to 1.3 (16)
2026-05-19 22:03:44 +02:00

129 lines
5.1 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
import Testing
@testable import OrgSocialKit
/// Tests for `inferredNick(from:)` the placeholder-nick heuristic used by
/// mention autocomplete for relay-only candidates whose profiles have not been
/// fetched yet. Cases are derived from real feeds registered on the public relay.
@Suite("inferredNick relay URL patterns")
struct URLNickTests {
// MARK: - Path-less host (e.g. social.orgro.org)
@Test("path-less host: penultimate segment of the hostname")
func pathlessHost() {
// https://social.orgro.org "orgro"
#expect(nick("https://social.orgro.org") == "orgro")
}
@Test("path-less host with subdomain: ignores leading segment")
func pathlessHostSubdomain() {
// Hypothetical: https://org.social.example.com "example"
#expect(nick("https://org.social.example.com") == "example")
}
// MARK: - /social.org at root (single path segment)
@Test("root social.org: falls back to host")
func rootSocialOrg() {
// https://rossabaker.com/social.org "rossabaker.com"
#expect(nick("https://rossabaker.com/social.org") == "rossabaker.com")
}
@Test("root social.org on srht: falls back to host")
func srhtRootSocialOrg() {
// https://gnomon.srht.site/social.org "gnomon.srht.site"
#expect(nick("https://gnomon.srht.site/social.org") == "gnomon.srht.site")
}
@Test("root social.org on github.io: falls back to host")
func githubIoRoot() {
// https://thesolarprincess.github.io/social.org "thesolarprincess.github.io"
#expect(nick("https://thesolarprincess.github.io/social.org") == "thesolarprincess.github.io")
}
// MARK: - /user/social.org (two-segment path, standard vhost pattern)
@Test("vhost-style: second-to-last segment is the username")
func vhostUsername() {
// https://host.org-social.org/andros/social.org "andros"
#expect(nick("https://host.org-social.org/andros/social.org") == "andros")
}
@Test("vhost-style: preserves case")
func vhostPreservesCase() {
// https://host.org-social.org/BALKIN/social.org "BALKIN"
#expect(nick("https://host.org-social.org/BALKIN/social.org") == "BALKIN")
}
@Test("two-segment path on personal domain")
func twoSegmentPersonal() {
// https://zweili.ch/org-social/social.org "org-social"
#expect(nick("https://zweili.ch/org-social/social.org") == "org-social")
}
@Test("tilde path on personal domain")
func tildePath() {
// https://muse-amuse.in/~punchagan/social.org "~punchagan"
#expect(nick("https://muse-amuse.in/~punchagan/social.org") == "~punchagan")
}
@Test("github pages two-segment: subfolder name")
func githubPagesSubfolder() {
// https://xlymian.github.io/org-social/social.org "org-social"
#expect(nick("https://xlymian.github.io/org-social/social.org") == "org-social")
}
// MARK: - Custom filename (ends in .org but not social.org)
@Test("custom .org filename: second-to-last segment is the nick")
func customOrgFilename() {
// https://cybervalley.org/org-social-leandro/org-social.org "org-social-leandro"
#expect(nick("https://cybervalley.org/org-social-leandro/org-social.org") == "org-social-leandro")
}
@Test("custom .org filename on github pages")
func customOrgFilenameGithubPages() {
// https://dharmatech.github.io/org-social-dharmatech/org-social.org "org-social-dharmatech"
#expect(nick("https://dharmatech.github.io/org-social-dharmatech/org-social.org") == "org-social-dharmatech")
}
@Test("wrbutros codeberg page: root .org filename falls back to host")
func codebergPageRootOrgFile() {
// https://wrbutros.codeberg.page/org-social.org "wrbutros.codeberg.page"
#expect(nick("https://wrbutros.codeberg.page/org-social.org") == "wrbutros.codeberg.page")
}
// MARK: - Deep paths (GitHub raw, Codeberg raw)
@Test("deep github raw path: segment before the filename")
func githubRawDeep() {
// https://raw.githubusercontent.com/fengbainuo/org-social/refs/heads/main/social.org "main"
#expect(nick("https://raw.githubusercontent.com/fengbainuo/org-social/refs/heads/main/social.org") == "main")
}
@Test("deep codeberg raw path: segment before the filename")
func codebergRawDeep() {
// https://codeberg.org/mester/CosasSociales/raw/branch/main/social.org "main"
#expect(nick("https://codeberg.org/mester/CosasSociales/raw/branch/main/social.org") == "main")
}
// MARK: - Non-.org path segments
@Test("non-.org final segment: last segment used as-is")
func nonOrgFinalSegment() {
// Hypothetical: https://example.com/feeds/alice "alice"
#expect(nick("https://example.com/feeds/alice") == "alice")
}
// MARK: - Helpers
private func nick(_ urlString: String) -> String {
guard let url = URL(string: urlString) else {
Issue.record("Invalid URL: \(urlString)")
return ""
}
return inferredNick(from: url)
}
}