2026-06-04 02:29:23 -07:00
|
|
|
@testable import ForgejoKit
|
2026-02-28 11:10:51 -08:00
|
|
|
import Foundation
|
|
|
|
|
import Testing
|
|
|
|
|
|
|
|
|
|
struct RepositoryServiceURLTests {
|
|
|
|
|
/// Creates a client with dummy credentials for URL construction tests.
|
|
|
|
|
private func makeClient() -> ForgejoClient {
|
|
|
|
|
ForgejoClient(serverURL: "https://forgejo.example.com", username: "user", password: "pass")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - fetchContents URL construction
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func makeURLContentsWithoutRef() throws {
|
2026-02-28 11:10:51 -08:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeURL(path: "/api/v1/repos/owner/repo/contents")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/contents")
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func makeURLContentsWithRef() throws {
|
2026-02-28 11:10:51 -08:00
|
|
|
let client = makeClient()
|
|
|
|
|
let queryItems = [URLQueryItem(name: "ref", value: "develop")]
|
|
|
|
|
let url = try client.makeURL(path: "/api/v1/repos/owner/repo/contents", queryItems: queryItems)
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/contents?ref=develop")
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func makeURLContentsWithRefAndSubpath() throws {
|
2026-02-28 11:10:51 -08:00
|
|
|
let client = makeClient()
|
|
|
|
|
let queryItems = [URLQueryItem(name: "ref", value: "feature/login")]
|
|
|
|
|
let url = try client.makeURL(path: "/api/v1/repos/owner/repo/contents/src/main.py", queryItems: queryItems)
|
|
|
|
|
#expect(url.query?.contains("ref=feature/login") == true)
|
|
|
|
|
#expect(url.path == "/api/v1/repos/owner/repo/contents/src/main.py")
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func makeURLFileContentWithRef() throws {
|
2026-02-28 11:10:51 -08:00
|
|
|
let client = makeClient()
|
|
|
|
|
let queryItems = [URLQueryItem(name: "ref", value: "v1.0")]
|
|
|
|
|
let url = try client.makeURL(path: "/api/v1/repos/owner/repo/contents/README.md", queryItems: queryItems)
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/contents/README.md?ref=v1.0")
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func makeURLWithEmptyQueryItems() throws {
|
2026-02-28 11:10:51 -08:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeURL(path: "/api/v1/repos/owner/repo/contents", queryItems: [])
|
|
|
|
|
#expect(url.query == nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - ref parameter nil-coalescence (same pattern used by fetchContents and fetchFileContent)
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func optionalRefProducesEmptyQueryItems() {
|
2026-02-28 11:10:51 -08:00
|
|
|
let ref: String? = nil
|
|
|
|
|
let queryItems = ref.map { [URLQueryItem(name: "ref", value: $0)] } ?? []
|
|
|
|
|
#expect(queryItems.isEmpty)
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func presentRefProducesQueryItem() {
|
2026-02-28 11:10:51 -08:00
|
|
|
let ref: String? = "main"
|
|
|
|
|
let queryItems = ref.map { [URLQueryItem(name: "ref", value: $0)] } ?? []
|
|
|
|
|
#expect(queryItems.count == 1)
|
|
|
|
|
#expect(queryItems.first?.name == "ref")
|
|
|
|
|
#expect(queryItems.first?.value == "main")
|
|
|
|
|
}
|
2026-03-11 13:53:55 -07:00
|
|
|
|
|
|
|
|
// MARK: - createRepository URL
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func createRepositoryURL() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeURL(path: "/api/v1/user/repos")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/user/repos")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - editRepository URL
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func editRepositoryURL() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeRepoURL(owner: "owner", repo: "repo", path: "")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - createLabel URL
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func createLabelURL() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeRepoURL(owner: "owner", repo: "repo", path: "/labels")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/labels")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - createMilestone URL
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func createMilestoneURL() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeRepoURL(owner: "owner", repo: "repo", path: "/milestones")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/milestones")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - addCollaborator URL
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func addCollaboratorURL() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let client = makeClient()
|
|
|
|
|
let encoded = ForgejoClient.encodedPathSegment("testbot")
|
|
|
|
|
let url = try client.makeRepoURL(owner: "owner", repo: "repo", path: "/collaborators/\(encoded)")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/collaborators/testbot")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - createFile URL
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func createFileURL() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let client = makeClient()
|
|
|
|
|
let url = try client.makeRepoURL(owner: "owner", repo: "repo", path: "/contents/hello.py")
|
|
|
|
|
#expect(url.absoluteString == "https://forgejo.example.com/api/v1/repos/owner/repo/contents/hello.py")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Payload encoding
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func createRepositoryPayloadEncoding() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let payload: [String: Any] = [
|
|
|
|
|
"name": "test-repo",
|
|
|
|
|
"description": "A test repo",
|
|
|
|
|
"private": false,
|
|
|
|
|
"auto_init": true,
|
|
|
|
|
]
|
|
|
|
|
let data = try JSONSerialization.data(withJSONObject: payload)
|
2026-06-04 02:29:23 -07:00
|
|
|
let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
|
2026-03-11 13:53:55 -07:00
|
|
|
#expect(dict["name"] as? String == "test-repo")
|
|
|
|
|
#expect(dict["auto_init"] as? Bool == true)
|
|
|
|
|
#expect(dict["private"] as? Bool == false)
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-15 03:06:27 -07:00
|
|
|
@Test func createFilePayloadEncoding() throws {
|
2026-03-11 13:53:55 -07:00
|
|
|
let payload: [String: Any] = [
|
|
|
|
|
"content": "base64content",
|
|
|
|
|
"message": "Add file",
|
|
|
|
|
"new_branch": "feature-branch",
|
|
|
|
|
]
|
|
|
|
|
let data = try JSONSerialization.data(withJSONObject: payload)
|
2026-06-04 02:29:23 -07:00
|
|
|
let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
|
2026-03-11 13:53:55 -07:00
|
|
|
#expect(dict["content"] as? String == "base64content")
|
|
|
|
|
#expect(dict["message"] as? String == "Add file")
|
|
|
|
|
#expect(dict["new_branch"] as? String == "feature-branch")
|
|
|
|
|
}
|
2026-02-28 11:10:51 -08:00
|
|
|
}
|